Webpack 3에서 CommonsChunkPlugin 설정 삽질 기록

문제 상황

프로덕션 배포 후 사용자들이 초기 로딩이 느리다는 피드백이 들어왔다. 확인해보니 bundle.js 하나가 2.1MB였다. React, Lodash, Moment 등 라이브러리 코드가 모두 하나로 묶여있었다.

CommonsChunkPlugin 적용

기본적인 vendor 분리부터 시작했다.

module.exports = {
  entry: {
    app: './src/index.js',
    vendor: ['react', 'react-dom', 'lodash', 'moment']
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: Infinity
    })
  ]
};

이렇게 하니 app.js (1.2MB)와 vendor.js (900KB)로 분리되었다. 하지만 app 코드를 수정할 때마다 vendor 파일의 해시값이 바뀌는 문제가 있었다.

Manifest 분리

Webpack 런타임 코드를 별도로 분리해야 vendor 캐싱이 제대로 작동했다.

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: Infinity
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
    minChunks: Infinity
  })
]

이제 app 코드를 수정해도 vendor 해시가 유지되었다. manifest는 5KB 정도로 작아서 inline으로 처리하는 것도 고려 중이다.

결과

  • 초기 로딩: vendor는 브라우저 캐시에서 로드
  • 배포 시: app.js만 새로 다운로드
  • 번들 사이즈: 2.1MB → 1.2MB + 900KB + 5KB

UglifyPlugin과 gzip 압축까지 적용하면 더 개선될 것 같다. Webpack 4에서는 이 부분이 더 쉬워진다는 얘기가 있던데 나오면 적용해봐야겠다.