webpack은 모던 자바스크립트 애플리케이션을 위한 정적 모듈 번들러입니다.
모던 애플리케이션의 경우 모듈 단위로 개발을 하는 경우가 많은데 직접 작성한 모듈 설치한 모듈들의 의존성을 파악하기란 너무나 어려운 일입니다.
저같은 경우 gulp, grunt 같은 테스크러너에 merge, minify, uglify등의 테스크를 등록하여 번들링(?) 하였었는데 테스크러너는 기본적으로는 의존성 모듈을 관리해주지 않았기 때문에 명시적으로 번들링할 대상들을 관리해줘야 한다는 불편함이 있었습니다. 때문에 개발자가 코드를 잘 작성해도 문제가 생기는등 관리 포인트가 늘어나는 아쉬운 점들이 있었습니다.
하지만 webpack은 모듈간 의존성을 스스로 파악하여 번들링해 주기 때문에 번거롭게 신경쓰지 않아도 된다는 장점이 있습니다. 그 외에도 여러가지 장점이 있겠지만 이번 포스팅에서는 webpack을 좀 더 잘 쓰기위한 주요 설정과 개인적으로 유용하다고 생각되는 몇가지 팁에 대해서 작성해 보도록 하겠습니다.
Webpack install & init
webpack과 webpack-cli를 설치하고 기본 값 셋팅된 package.json 파일을 생성합니다.
번들링시 mode에 따른 built-in 최적화를 수행합니다. process.env.NODE_ENV 를 설정해도 mode를 자동으로 set 해주지는 않으며 기본값으로 ‘production’ 모드를 가집니다.
Example
1 2 3
module.exports = { mode: 'production' };
option
description
development
process.env.NODE_ENV 를 development 으로 설정합니다. NamedChunksPlugin,NamedModulesPlugin 활성화 합니다
production
process.env.NODE_ENV 를 production 으로 설정합니다. FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 및 TerserPlugin을 사용합니다.
빌드 산출물의 경로와 파일명을 설정합니다. name, hash, chunkhash 속성을 사용할 수 있습니다.
output option
name: 엔트리 명에 따른 output
hash: webpack build에 따른 output
chunkhash: chunk에 따른 output
1 2 3 4 5 6 7
{ output: { path: '/home/cdn/assets/[hash]', // 빌드된 번들 파일이 위치할 파일의 절대 경로 publicPath: 'http://script.auction.co.kr/assets/[hash]/', // 브라우저가 참고할 번들링 결과 파일의 URL주소(CDN 호스트) 반드시 앞뒤 / 추가해 줘야합니다. filename: '[name].js'// entry의 key name => name 으로 참조 됩니다. } }
module.exports = { plugins: [ new webpack.optimize.UglifyJsPlugin(), new webpack.ProvidePlugin({ $: 'jquery' }), // 모든 모듈에서 사용할 수 있도록 해당 모듈을 변수로 변환한다. // 즉 각 모듈(파일)에서 매번 import할 필요 없이 해당 변수를 통하여 참조가능 new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify('5fa3b9'), BROWSER_SUPPORTS_HTML5: true, TWO: '1+1', 'typeof window': JSON.stringify('object') }), // 웹팩 번들링 시작하는 시점에 사용 가능한 상수값 정의 가능 // 개발계, 테스트계에 따라 다른 설정 적용시 유용하다. newManifestPlugin({ fileName: 'manifest.json', basePath: './dist/' }), // 번들링시 생성되는 코드에 대한 정보들을 json 파일 안에 담아줘 라이브러리들간 의존성 파악 용의 ] }
devServer를 사용하여 빌드를 위한 개발 서버를 구성할 수 있습니다. webpack 자체에서 제공하는 개발 서버로 빠른 리로딩 기능을 제공하며 번들된 파일은 in memory에 올라가기 때문에 가시적으로 볼 수 없습니다. 프로토타이핑이 끝나고 배포할 때 실제 bundle 파일이 생성됩니다.
1
npm i webpack-dev-server -D
Example
1 2 3 4 5 6 7 8 9 10 11
module.exports = { //... devServer: { publicPath: '/assets', // 절대경로로 지정하고 항상 /를 앞뒤에 붙여야 한다. contentBase: path.join(__dirname, 'dist'), // 서버가 로딩할 static 파일 경로 // contentBase: false, // 비활성화 compress: true, // gzip 압축 방식을 이용하여 웹 자원의 사이즈를 줄인다. // 파일을 줄이는게 아니라 서버와 클라이언트간 압축방식 정의 port: 9000 } };
Run server with cli
1
webpack-dev-server--open
Run server with script
1
"scripts":{"start":"webpack-dev-server"}
1
npm start
Webpack 사용시 알아두면 좋은 TIP
Webpack 빌드를 위한 개발 서버 구성
앞서 언급된 devServer를 이용하는 방법도 있지만 이미 서버가 구성된 경우에는 webpack을 미들웨어로 구성하여 서버와 연결할 수 있습니다.
webpack-dev-middleware
기존에 구성한 서버에 weback 에서 컴파일한 파일을 전달하는 middleware wrapper로 webpack에 설정한 파일을 변경시, 파일에 직접 변경 내역을 저장하지 않고 메모리 공간을 활용합니다. (변경된 파일내역을 파일 디렉토리 구조안에서는 확인이 불가능합니다.)
module.exports = { entry: { main: './app/index.js', vendor: [ 'moment', 'lodash' ] }, output: { filename: '[name].js', // main.js, vendor.js path: path.resolve(__dirname, 'dist') }, module: {}, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor'// output bundle file name // or names: ['vendor', 'manifest'] // 매 번들시 번들파일에 웹팩 초기화 하는 부트스트랩 코드가 들어가는데 manifest.js 그 부분까지 분리해 낼 수 있다. 매번 번들되는 코드의 양을 좀 더 줄일 수 있다. })
// and 번들된 파일 관리 목록 json // npm i webpack-manifest-plugin --save-dev newManifestPlugin({ fileName: 'manifest.json', basePath: './dist/' }) ] }
join, resolve 차이점
webpack config 작성이나 nodejs 작업시 join, resolve를 많이 접할 수 있습니다. 개인적으로 헷갈렸던 두 메소드의 차이점에 대해서 확인해 보겠습니다.
path.join()
OS의 파일 구분자를 이용하여 파일 위치를 조합합니다. OS의 파일 구분자를 이요하기 때문에 결과값이 OS에 따라 달라짐에 유의해야합니다.
join()의 경우 문자열을 합치기만 하지만 resolve()는 오른족에서 왼쪽으로 파일 위치를 구성해가며 유효한 위치를 찾습니다. 만약 결과 값이 유효하지 않으면 현재 디렉토리가 사용되며 반환되는 위치 값은 항상 absolute URL 이고 absolute URL이 만들어 지면 종료됩니다.
파라미터에 들어온 유효하지 않은 path 까지 알아서 제거해 주기 때문에 항상 유효한 path만 받을 수 있다는 장점이 있습니다.
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif'); // 현재 폴더 위치가 /home/myself/node 라면 // '/home/myself/node/wwwroot/static_files/gif/image.gif'
정리
webpack 주요 설정 속성과 몇가지 팁에 대해서 알아봤습니다. zero configuration 이 트렌드가 되는 요즘 configpack 이라는 놀림을 받고 있는 webpack 이지만 점점 더 좋아질 것으로 생각합니다. 지금도 react나 vue를 위한 설정은 cli로 아무런 설정없이 바로 사용이 가능하며 custom을 위해 eject를 사용하는 방법도 있습니다.
설정 없이 자동으로 된다 해도 아직까지는 설정에 대한 학습이 필수라고 생각하기 때문에. 가장 정리가 잘 되어있고 친절한 webpack.js.org를 자주 열어보고 학습하는 것을 추천드립니다.