webpack4로 바꾸기
webpack4가 오늘 릴리즈 되었다.
속도가 90%까지 빨라진다고 해서 번들링 속도에 작업지연을 겪고 있던터라 얼른 적용해보았다. 확실히 번들링 속도가 빠르다!!
아직까진 마이그레이션 가이드가 완벽하지는 않은것 같아서 적용해보면서 겪은 몇가지 이슈를 공유해보고자 한다.
Webpack4는 뭐가 바뀌었을까. 몇가지 간단히 요약하면, (변경사항은 더 많다)
- 빨라졌다.
- 플러그인 및 chunk module관계 최적화
- mode라는게 생겼다.
- 플러그인과 loader가 built-in되거나 바뀌었다.
- tapable을 통해 고도화가 가능하다.
- web assembly를 지원한다.
이 정도다. 그런데 webpack4는 이전 버전과의 호환을 보장해주지 않아서 꽤나 많이 바꿔야한다.
process.env를 더 이상 쓰지 않아도 된다.
매번 npm script에서 cross env로 빌드하면서 넣어주던 노드환경변수들을 더이상 쓸 필요가 없다.
//더 이상 필요없다.
"dev": "cross-env NODE_ENV=development webpack",
이젠 mode라는게 생겼다. –mode옵션으로 주어도 되고 config에 mode를 넣어주어도 된다.
package.json의 scripts
"dev": "webpack --mode development",
"build": "webpack --mode production",
기본값들은 development와 production이고 플러그인 설정들도 자동으로 설정되어 있다. 따로 설정하지 않아도 scope hoisting, tree shaking, minification등등은 production환경에서만 동작한다.
번들의 값을 바꾸기 위해 process.env.NODE_ENV 환경변수를 설정하고 싶으면 (define plugin)
optimization.nodeEnv
옵션으로 대체 가능하다. default는 모드의 값이다.
version을 업데이트 해야한다.
webpack4로 올리면 webpack3에서 잘 쓰고 있던 lib들도 안되는 것들이 많다.
webpack-dev-server는 3.0으로 업데이트 해줘야 한다.
webpack-cli(2.0.0)도 깔아야 블드가 된다..
바벨의 경우는 플러그인들이 @babel안으로 통합이 되었다.
babel-loader의 dev-dependency를 참조하면 된다. babel-lodaer도 8.0베타로 업그레이드 해줘야 한다.
package.json
"devDependencies": {
"babel-eslint": "^8.0.0",
"babel-loader": "^8.0.0-beta.1",
"@babel/cli": "7.0.0-beta.40",
"@babel/core": "7.0.0-beta.40",
"@babel/preset-env": "7.0.0-beta.40",
"@babel/preset-flow": "7.0.0-beta.40",
"@babel/preset-stage-0": "7.0.0-beta.40",
"@babel/register": "7.0.0-beta.40",
....
}
json-loader는 더이상 사용하지 않는다.
built-in되었다. config과 dependency에서 제거해도 된다.
url-loader는 구버전의 file-loader를 써서 호환이 안된다.
file로더를 를 url-loader의 max로 분기해서 쓰고 있었다면 최신버전으로 업데이트 하자(1.1.9)
commonchunk plugin이 없어졌다.
여러 플러그인들이 optimization이라는 config에 통합이 되었다. 그 중 하나가 commonchunk plugin인데 아래와 같이 splitChunks라는 옵션을 이용하면 된다.
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
enforce: true,
chunks: 'all'
}
}
}
},
UglifyJsPlugin의 옵션을 그대로.
트리쉐이킹의 필수인 UglifyJsPlugin은 optimization의 minimize
로 대체가 되었는데 boolean값만 받을 뿐 기존 옵션그대로 쓰는게 잘 지원이 안된다. 알파때 이미 여러번 제기가 되어서 해결은 가능하다.
기존의 사용하던 옵션으로 쓰려면 아래와 같이 minimizer라는 옵션에 배열로 써야한다.
optimization: {
minimize: false,
minimizer : [new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
unused: true
},
mangle: false,
beautify: true,
output: {
comments: false
}
}
})],
},
하지만 이렇게 하면 minimize:false
옵션이 unused옵션을 사용안함으로 오버라이드 하면서 tree shaking이 안된다. 혹시 해결한 분이 있으면 알려줬으면 한다.
그래서 minimize 옵션은 false로 바꾸지 않고 production에서만 작동하도록 원래설정대로 놔두는게 낫다.
ExtractTextPlugin는 아직 완벽하게 사용이 불가하다.
css를 파일로 만들어주는 ExtractTextPlugin는 아직 옵션 그대로 쓸 수 없다. 다음 버전부터 작업된다고 한다.
그래서 ExtractTextPlugin에서 임시버전을 만들었다. ^4.0.0-alpha.0로 다운받고 쓰면 된다.
multi target 사용이 dev-server에서는 안된다.
webpack config에 multi target으로 옵션을 분리해놓고 쓰고 있었는데 build는 되지만 webpack-dev-server에서는 아래와 같은 에러를 뱉으면서 작동하지 않는다.
Error: Plugin could not be registered at ‘compile’. Hook was not found. BREAKING CHANGE: There need to exist a hook at ‘this.hooks’. To create a compatiblity layer for this hook, hook into ‘this._pluginCompat’.
이유는 MultiCompiler지원을 아직 안해주어서 그러는 건데 이는 곧 해줄거라 믿는다. https://github.com/webpack/webpack-dev-server/issues/1301
결론
버그도 많고 아직은(오늘은) 시기상조인것 같다.
참고 https://medium.com/webpack/webpack-4-released-today-6cdb994702d4 https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a https://medium.com/webpack/webpack-4-migration-guide-for-plugins-loaders-20a79b927202