Webpack5에서는 기본적으로 Production 모드일 때 내장 최적화(built-in optimizations)를 진행해주는데 그 중에 TerserPlugin이 포함되어 있다.
TerserPlugin는 자바스크립트 코드를 압축화하고 난독화해주는 플러그인
production mode 일 경우,
Sets process.env.NODE_ENV on DefinePlugin to value production. Enables deterministic mangled names for modules and chunks, FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin and TerserPlugin.
State size: 원래 모듈의 사이즈
Parsed size: 변환 이후의 사이즈 번들 크기를 줄이려면 해당 사이즈를 확인해야 한다.
Gzip size: gzip 압축 이후 사이즈
아무 작업을 하지 않았을 경우 대부분 하나의 Bundle 파일이 보일 것이다. 하지만 Bundle의 사이즈가 커지게 되면 페이지의 첫 진입이 느려지는 불편함이 발생 할 수도 있기 때문에 Code Splitting이라는 기술을 이용하여 Bundle의 코드를 특정한 기준을 가지고 다양한 Bundle로 분할하게 되었다.
Code Splitting는 크게 Entry Points 와 Dynamic Import 방식으로 접근할 수 있으며 Entry Points의 경우 엔트리 청크 사이에 중복된 모듈이 있는 경우 두 번들에 모두 포함때문에 Prevent Duplication 작업이 추가적으로 필요하다.
import Main from '../pages/MainPage';
import Search from '../pages/SearchPage';
import Notfound from '../pages/NotFoundPage';
const ROUTE = [
{ path: PATH.MAIN, Component: Main, auth: false },
{ path: PATH.SEARCH, Component: Search, auth: false },
{ path: PATH.NOT_FOUND, Component: Notfound, auth: false },
];
나의 경우에는 React Router를 이용하여 url에 따라 컴포넌트를 불러오고 있기 때문에 해당 컴포넌트들을 기준으로 Code Splitting 작업을 진행하였다.
사실 Code Splitting을 작업할만큼 기존의 Bundle 사이즈가 크지 않지만 공부할겸 진행해본 과정이였는데 약 0.04MB 정도 줄어든 것을 확인할 수 있다.
여기서 조금 더 욕심을 내면 Vendor Chunk를 활용할 수 있다.
Vendor Chunk는 node_moudules와 같이 외부에서 관리되는 모듈들만 따로 분류하는 chunk로 Vendor Chunk를 사용하면 매번 빌드될때마다 hash값이 바뀌지 않기 때문에 재배포하여도 이미 캐싱된 chunk 파일을 활용하여 조금 더 빠르게 로딩할 수 있는 장점이 있다.
그럼 react, react-dom, react-router와 같이 외부에서 관리되면서 웬만하면 바꿀일이 없는 core 모듈들을 분리해보겠다.
// webpack.prod.js
optimization: {
splitChunks: {
cacheGroups: { // 특정 조건에 따라서 청크파일을 생성하는 규칙 정의
default: false,
vendor: {
chunks: 'all',
name: 'vendor',
test: /[\\/]node_modules[\\/](react|react-dom|react-router)[\\/]/,
filename: '[name].[chunkhash].js',
}
},
},
},
이제 vendor로 분리된 chunk(Bundle 파일)는 재배포가 되어도 동일한 hash값을 가지고 있기 때문에 사용자 입장에서 브라우저에 캐싱된 파일을 불러와 그만큼 더 빠르게 로딩할 수 있게 된다.