개발 후 최종적으로 앱을 배포하기위해 번들링하는 과정에서 번들된 결과물의 용량이 커지게 된다면 브라우저 성능에 영향을 준다.
그래서 결과물을 여러개로 쪼개거나 코드를 압축하는 등의 최적화하는 과정이 필요하다.
우선 웹팩 실행 시 주어진 환경변수 production, development값에 따라 mode를 설정하여 플러그인을 사용할지 말지를 정할 수 있다.
// webpack.config.js:
const mode = process.env.NODE_ENV || "development";
module.exports = {
mode,
}
개발 시에는 기본적으로 development모드
를 사용하며 배포 시 빌드하는 과정은 production모드
로 동작하게끔 스크립트도 수정한다.
// package.json:
{
"scripts": {
"start": "webpack-dev-server --progress",
"build": "NODE_ENV=production webpack --progress"
}
}
HtmlWebpackPlugin이 html 파일을 압축한것 처럼 css파일도 압축할 수 있는 플러그인이 존재한다.
webpack4: optimize-css-assets-webpack-plugin
Webpack5: css-minimizer-webpack-plugin
$ npm i -D css-minimizer-webpack-plugin
// webpack.config.js:
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: mode === "production" ? [new CssMinimizerPlugin()] : [],
},
}
terser를 사용 하여 JavaScript를 최소화하는 플러그인으로 terser의 옵션을 사용하여 실수로 제거하지 않은 콘솔 로그등을 제거할 수 있는 기능이 존재한다.
$ npm i -D terser-webpack-plugin
// webpack.config.js:
const TerserPlugin = require("terser-webpack-plugin")
module.exports = {
optimization: {
minimizer:
mode === "production"
? [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // 콘솔 로그를 제거한다
},
},
}),
]
: [],
},
}
js파일내에서 console.log가 제거된것을 확인 할 수 있다.
결과물을 여러개로 쪼갬으로써 브라우저의 다운로드 속도를 높일 수 있다. ( 큰 파일 하나를 다운받는 속도보다 작은 파일을 여러개 받는 것이 속도가 더 빠르다고 한다. )
// webpack.config.js
module.exports = {
entry: {
main: "./app.js",
controller: "./list.js"
},
}
기본적으로 웹팩설정파일에서 entry를 여러개로 둘수있는데 코드가 분리되면서 중복되는 코드가 존재하기 때문에 플러그인의 힘이 필요하다. 이 경우는 SplitChunksPlugin
를 사용하면 된다.
(위의 entry에서 axios관련된 코드가 중복적으로 들어간 것을 확인할 수 있었다.)
// webpack.config.js:
module.exports = {
optimization: {
splitChunks: {
// 모든 유형의 청크를 포함
chunks: "all",
},
},
}
이제 중복된 코드(axios관련)는 154.js란 파일에 담기게 되었다.
예를 들어 axios같은 써드파티 라이브러리들은 이미 빌드가 되어있기 때문에 빌드 과정에서 제외될수 있도록 externals속성을 사용하면 좋다.
그리고 추가적으로 써드파티 라이브러리의 번들된 결과물을 가져와야하기 때문에 copy-webpack-plugin
를 이용하여 라이브러리를 웹팩 아웃풋 폴더에 옮기고 index.html에서 로딩하게끔 설정해야한다.
$ npm i -D copy-webpack-plugin
// webpack.config.js:
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
externals: {
axios: "axios", // axios 제외
},
// 생략
plugins: [
new CopyPlugin({ // 라이브러리 복사
patterns: [
{
from: "./node_modules/axios/dist/axios.min.js",
to: "./axios.min.js", // 목적지 파일로 복사
},
],
}),
],
}
axios는 번들과정에서 제외시켰기 때문에 이제 번들 결과물에서 찾을 수 없고 대신 node_modules/axios에서 이미 번들된 결과물을 복사해왔다.
htmlwebpacPlugin이 번들된 결과물을 index.html내부에 주입해주지만 번들결과에서 제외시켰기 때문에 직접 index.html에 script문을 추가해줘야 axios를 정상적으로 사용할 수 있게된다.
<!--- ./src/index.html --->
<h1>webpack test</h1>
<ul id='list'></ul>
<script type="text/javascript" src="axios.min.js"></script>
</body>
</html>
이렇게 externals로 써드파티 라이브러리를 분리함으로써 용량이 감소뿐만 아니라 빌드시간도 줄어든다는 장점이 있다.
엔트리를 직접 분리하는 방식보다는 자동으로 하는 방식이 좋은데 관련해서는 다이나믹 임포트
키워드를 통해 더 알아봐야한다.
현재 웹팩5을 사용하고 있는데 해당 패키지는 웹팩의 패키지를 낮춰야한다고 한다.
optimize-css-assets-webpack-plugin 문서에 가보니 For webpack v5 or above please use css-minimizer-webpack-plugin instead.
css-minimizer-webpack-plugin를 대신 사용하라고 한다.
그래서 css-minimizer-webpack-plugin를 사용하기로
해당 강의는 webpack4 기준에 맞춰져있으며 똑같이 따라하기보다는 직접 오류를 겪어보며 해결해보고싶어서 webpack5 기준으로 작성을 해왔고 깊은 부분까지 다뤄보지는 않았지만 웹팩을 직접 다뤄보면서 다른 프로젝트에 존재하는 웹팩 설정의 의도를 전반적으로 이해하는데 도움이 되었다.