Webpack은 오픈 소스 자바스크립트 모듈 번들러라고 한다. 모듈 번들러라는 말이 어려울 수 있는데, 쉽게 얘기하면 HTML 파일에 들어가는 자바스크립트 파일들을 하나의 자바스크립트 파일로 만들어주는 방식을 모듈 번들링이라고 한다. 실제로 Webpack으로 코드를 build 해보면 정해놓은 폴더 안의 .js 파일들이 생성된다. 이 안은 여러 곳에 퍼져있는 내 모든 코드들이 합쳐져 일정 개수의 파일로 만들어져있고(.html, .js, .css 등) 특정 파일에서 특정 단어를 검색을 해보면 검색도 된다. 하지만 그 파일을 가지고 코드를 유추하기는 거의 불가능할 정도로 만들어져있다.
reference: https://webpack.kr/
Webpack의 주요 개념은 네가지가 있다. 간단하게 코드는 실제 내 코드에서 해당 부분을 가져와보았다.
entry / output / loader / plugin
Webpack은 모든 파일을 모듈로 관리한다. Webpack에서 모듈들은 많아질수록 서로에게의 의존성이 높아진다. 그 의존성의 시작점을 entry 라고 한다.
const config: webpack.Configuration = merge(baseConfig, {
mode: 'production',
entry: './src/index.tsx',
...
Webpack을 이용하여 build를 하고, 번들된 파일의 위치를 지정하는 것이 output 이다.
...
output: {
path: path.resolve(__dirname, '..', 'dist'),
publicPath: '../dist/',
filename: 'bundle.js'
},
Webpack은 사실 javascript밖에 모른다. css, scss, babel, file 등 loader로 등록을 해주어야 Webpack이 bundle 할 때 인식을 할 수 있다.
/**
* Transfile TS files or TSX files to JS files.
* And run babel at JS files to transfile ES6+ code to ES5.
*/
{
test: /\.tsx?$/,
use: {
loader: 'awesome-typescript-loader',
options: {
silent: true,
useBabel: true,
useCache : true,
babelCore: '@babel/core',
babelOptions: {
babelrc: false,
presets: babelPresets
}
}
}
},
loader는 파일을 해석하고 변환하는 과정에 관여하여 모듈을 처리한다면, plugin은 해당 결과물의 형태를 바꾸는 역할을 하므로 번들링된 파일을 처리한다는 점이 다르다. 결과물에서 스타일 코드만 뽑아서 별도 css 파일로 만들어 역할에 따라서 파일을 분리하는 것이 가능하다.
plugins: [
/**
* Add production environment.
* Ref: https://webpack.js.org/plugins/define-plugin/
*/
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.FLUENTFFMPEG_COV': false
}),
Babel은 Javascript Compiler다. 단순히 컴파일을 위한 것이 아닌, 브라우저를 위한 Transpiler 이다. Javascript는 계속해서 발전되고 있는 언어이고, 그로 인해 새로운 문법 또한 생긴다. Babel은 브라우저들이 최신 Javscript 코드를 읽지 못하는 것을 위해 최신 버젼의 Javascript를 브라우저가 읽을 수 있도록 옛날 버젼의 Javascript 코드로 변환해주는 역할을 한다.
Babel은 세가지 단계로 진행된다.
Parsing과 Printing은 이 Babel이 맡고있지만, Transforming 단계는 외부 플러그인이 맡고있다. 그것이 Babel Plugin이다.
Babel이 코드를 어떤식으로 변환시킬지에 대한 규칙을 나타낸다.
{
"presets": [
"@babel/preset-react",
["@babel/preset-env", {
"targets": {
"browsers": [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 9"
]
}
}]
],
"plugins": [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
["import", { "libraryName": "antd", "style": true }]
]
}
우리는 Webpack을 알고 있으니 'babel-loader'로도 사용할 수 있다. build를 할 때 자동으로 Babel이 처리할 수 있게 할 수 있다.
/**
* Run babel at JS files to transfile ES6+ code to ES5.
*/
{
test: /\.jsx?$/,
exclude: /node_modules\/(?![@polymer/lit\-element|lodash\-es])/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
compact: true,
presets: babelPresets
}
}
},
Babel plugin들은 공식 docs에서 확인할 수 있다.