[webpack] webpack.config.js 훑어보기
웹팩은 자바스크립트 모듈 번들러(bundler)이다. bundle
은 묶음이란 뜻을 가지고 있는데, 웹팩은 여러 자바스크립트 모듈을 하나의 자바스크립트 파일로 묶어주는 역할을 한다.
웹팩 4.0 버전 이상부터 웹팩은 기본적으로 프로젝트의 src/index.js
파일을 dist/main.js
파일로 번들링해준다. 하지만 우리의 프로젝트는 저마다 다른 구성을 이루고 있고, 모든 프로젝트를 동일한 조건으로 번들링한다는 것은 거의 불가능할 것이다. 웹팩에서는 이러한 환경을 위해 각 프로젝트의 루트 폴더에 webpack.config.js
파일을 생성하도록 하고 있다. webpack.config.js
파일에 내 프로젝트에 적용된 다양한 옵션을 설정하면 웹팩이 해당 파일을 자동으로 읽고 이에 맞게 번들링을 해준다.
wepback.config.js
파일에서는 아래의 옵션을 설정할 수 있다.
entry
output
module
plugins
resolve
mode
devtool
target
externals
webpack 5
버전을 중심으로 주로 사용되는 옵션을 알아보자.
Entry
entry
는 웹팩이 어떠한 파일을 기준으로 삼고 번들링할 것인지 설정한다. 웹팩은 entry
로 지정된 파일이 다른 어떠한 모듈을 import
하고 있는지 확인하고 함께 번들링 한다.
module.exports = {
entry: ‘./src/index.js’
};
네이밍
entry
에 객체를 전달하면 번들링한 결과물의 이름을 설정해줄 수도 있다. 각 key
는 번들링되는 파일의 이름을 의미하고 value
는 해당 파일의 엔트리 파일을 지정한다.
// home.js, about.js, concat.js 파일을 home, about, concat 이름의 파일로 번들링한다.module.exports = {
entry: {
home: './home.js',
about: './about.js',
contact: './contact.js',
},
};
다중 엔트리 포인트
entry
에 배열을 전달하면 여러 파일을 엔트리로 지정할 수 있다.
module.exports = {
entry: {
home: ['./home.js', './about.js', './contact.js'],
},
};
엔트리 기술자 (descriptor)
entry
에 객체를 전달하면 엔트리에 추가할 옵션을 설정할 수 있다.
module.exports = {
entry: {
catalog: {
import: './catalog.js',
filename: 'pages/[name].js',
dependOn: 'shared',
},
shared: ['react', 'react-dom', 'redux', 'react-redux'],
},
};
import
: 엔트리 파일을 지정한다.filename
: 기본적으로 번들링한 결과물의 경로와 이름은output
옵션에서 작성하지만entry
에서도 지정할 수 있다. 파일명에[name]
을 입력하면 위에서 지정한 번들링한 결과물의 이름을 적용할 수 있다.dependOn
: 기본적으로 모든 번들링한 결과물은entry
가 의존하고 있는 모듈의 코드를 포함하고 있다.dependOn
옵션을 사용하면 해당 옵션의 모듈을 공유할 수 있다.
// app 파일은 react-vendors의 모듈을 직접 포함하지 않지만 react-vendors 파일의 모듈을 공유한다.module.exports = {
//...
entry: {
app: {
import: './app.js',
dependOn: 'react-vendors'
},
'react-vendors': [
'react',
'react-dom',
'prop-types'
],
},
};
context
context
는 entry
와 loaders
옵션의 기본 디렉토리를 절대경로로 설정한다. 웹팩에서는 기본적으로 현재 디렉토리를 기본 디렉토리로 적용하고 있기에 실무에서는 잘 사용하지 않는 듯하다. 하지만 context
를 설정해주면 webpack.config.js
파일의 경로가 현재 경로에 의존하지 않을 수 있기에 웹팩 공식 문서에서는 이를 명시적으로 설정할 것을 권유하고 있다.
// 사용되는 entry와 loader 파일 경로를 /디렉토리/app/으로 설정한다.const path = require('path');module.exports = {
context: path.resolve(__dirname, 'app'),
};
Output
output
옵션은 번들링한 결과물의 옵션을 설정한다.
module.exports = {
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'public/assets'),
publicPath: '/assets/',
},
};
filename
번들링한 결과물의 이름을 지정한다. [name]
을 사용하면 entry
에서 전달한 객체의 key
로 파일명이 설정된다. (웹팩에서는 대괄호 []를 이용하여 템플릿 문자열을 사용할 수 있다. [name]
이 이외에도 [id]
, [hash]
를 이용하여 파일명을 설정할 수 있다.)
path
번들링한 결과물이 저장되는 경로를 지정한다.
publicPath
웹팩으로 output.path
의 경로에 번들링 되는 결과물을 브라우저에서 접근할 때 publicPath
에 설정한 경로로 접근할 수 있다. 또한 webpack.config
파일에 설정한 loader
(file-loader
, url-loader
등)에서 처리하는 파일(폰트, 이미지 등)의 경로에 prefix로 적용되는 경로를 설정한다. publicPath
옵션에 상대경로를 지정하면 HTML 페이지에 상대적인 경로로 되며, CDN 서버나, 프로토콜, 혹은 절대 경로 또한 publicPath
의 옵션으로 지정할 수 있다.
// 브라우저에서 '/assets/app.js' 파일을 요청하면 '/public/assets/app.js' 경로에 있는 파일을 불러온다.module.exports = {
output: {
filename: 'app.js',
path: path.resolve(__dirname, 'public/assets'),
publicPath: '/assets/',
},
};
Module
웹팩은 원래 자바스크립트와 json 파일 밖에 해석하지 못하지만 loader
를 이용하면 HTML, CSS, Image등 다른 형식의 파일을 해석하고 모듈로 변환시킬 수 있다. loader
는 module
속성의 rules
에 로더의 속성이 담긴 객체가 배열로 적용된다.
// css 파일을 해석하고 html에 inline-style로 추가해주는 로더를 추가한다. css-loader가 먼저 적용된 뒤 style-loader가 적용된다.module.exports = {
module: {
rules: [{
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader, 'css-loader'],
}],
},
};
test
:loader
를 이용하여 변환될 파일의 확장자를 설정한다. 주로 정규표현식을 이용하여 적용한다.use
: 어떠한loader
를 사용할지 작성한다. 배열에 여러 개의loader
를 적용할 수 있는데 오른쪽에서 왼쪽 순으로loader
가 적용된 후 컴파일 된다.exclude
:loader
가 적용되지 않을 파일을 설정한다. 주로 정규표현식을 이용하여 적용한다.
use
에 배열 대신 객체를 적용하면 아래와 같이 loader
의 옵션을 설정할 수 있다.
// babel loader를 추가한다.module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
{'targets': 'defaults'}
]
}
}
}
]
}
}
loader
: 적용할loader
를 설정한다.options
:loader
에 적용되는 옵션을 설정한다.@babel/presets-env
는 최신 자바스크립트를target
에 설정한 하위 브라우저에서도 동작할 수 있도록 변환해준다.
Plugins
plugins
옵션은 웹팩 번들링 과정을 커스터마이징 하는데 사용되는 플러그인을 배열로 적용한다. loader
는 파일을 해석하고 변환하는 과정에 작용하지만 plugins
는 번들링한 결과물에 작용한다. 웹팩은 webpack.[plugin-name]
의 이름을 가진 플러그인들을 내장하고 있다.
module.exports = {
plugins: [
new webpack.DefinePlugin(),
],
}
Resolve
resolve
옵션은 웹팩이 모듈을 어떻게 해석할지 설정한다. 예를 들어 파일 내에서 lodash
모듈을 import한다면 resolve
옵션을 이용해 어디서 lodash
모듈을 가져올지 변경할 수 있다.
alias
파일 내에서 모듈을 쉽게 import
하거나 require
할 수 있도록 설정한다. 아래와 같이 설정해 준다면,
module.exports = {
resolve: {
alias: {
Utilities: path.resolve(__dirname, 'src/utilities/'),
Templates: path.resolve(__dirname, 'src/templates/'),
},
},
};
상대 경로로 모듈을 import
하는 대신
import Utility from '../../utilities/utility';
아래와 같이 import
할 수 있다.
import Utility from 'Utilities/utility';
extensions
모듈을 import
할 때 확장자를 적지 않더라도 extensions
옵션의 확장자를 왼쪽에서 오른쪽으로 적용할 수 있다. 이 옵션을 적용하면 기존 웹팩에 적용된 extensions
가 적용되지 않는다.
아래와 같이 적용한다면,
module.exports = {
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json'],
},
};
아래와 같이 모듈을 import
할 수 있다. 웹팩은 extensions
옵션의 왼쪽에서부터 오른쪽으로 확장자를 적용해 해당하는 모듈을 import
한다.
import File from '../path/to/file';
Mode
웹팩이 번들링하는 모드를 설정할 수 있다. production
혹은 development
를 설정한다.
아래와 같이 wepback.config.js
파일에 mode
옵션을 설정하거나
module.exports = {
mode: 'development',
};
cli
에서 아래와 같이 webpack을 실행할 수도 있다.
webpack --mode=development
Devtool
source map
의 스타일을 설정한다. source map
은 원본 파일과 번들링한 파일을 매핑해주는 기능이다. 빌드 시에는 모든 파일이 압축되는데 source map
은 압축된 파일이 원본 파일의 어느 부분에 해당하는지 알게 해준다. source map
을 이용하면 개발 시 오류가 발생했을 때 디버깅을 쉽게 할 수 있다.
source map
스타일은 다양하며 모드에 따라 설정할 수 있다. 아래 링크에서 전체 source map
옵션을 확인할 수 있다.
https://webpack.js.org/configuration/devtool/#devtool
Target
번들링한 자바스크립트의 타겟 버전을 설정한다. node
혹은 web
을 지정할 수 있으며, node
와 web
의 각 버전 또한 지정할 수 있다.
module.exports = {
target: 'node12.18',
};
target
의 값이 배열로 설정될 경우 공통 기능의 하위 버전으로 번들링한다.
아래와 같이 설정할 경우 web
용 ES5
만 사용한다.
module.exports = {
target: ['web', 'es5'],
};
아래와 같이 서로 다른 환경의 타겟을 같이 설정할 수 없다.
module.exports = {
// ...
target: ['web', 'node'],
};
번들링한 결과물이 IE11에서도 실행될 수 있도록
target: ['web', 'es5']
을 설정했더니webpack-dev-server
에서HMR
이 동작하지 않는 오류가 발생했다.target: 'es5'
도 동일하게 동작하지 않았고target: 'web'
만HMR
이 정상적으로 동작하였다.
https://webpack.js.org/configuration/devtool/
externals
번들링할 때 제외시킬 파일을 설정한다. externals
에 설정한 모듈을 import
할 경우 번들링 단계에서 해당 모듈이 존재하지 않더라도 에러가 발생하지 않는다. 런타임 환경에서 추가된 외부 라이브러리를 entry
파일에서 사용할 경우 externals
옵션을 설정하면 된다.
예를들어 html 파일에 jQuery 스크립트 파일을 임베딩할 경우,
<script
src="https://code.jquery.com/jquery-3.1.0.js"></script>
아래와 같이 externals 옵션을 설정한다.
// 파일에서 import(‘jquery’)를 하면 global.jQuery를 가져온다.module.exports = {
externals: {
jquery: 'jQuery',
},
};
entry
파일 내부에선 아래와 같이 import
해서 사용할 수 있다.
import $ from 'jquery';
$('.my-element').animate(/* ... */);