Webpack - 번들 최적화

김정욱·2022년 4월 3일
1

Webpack

목록 보기
5/5
post-thumbnail

[ Webpack Bundle Analizer ]

[ 개요 ]

  • npm package : webpack-bundle-analyzer
  • 웹팩 번들 분석 플러그인
  • 번들링되는 모듈들을 분석해서 시각적으로 표현해주는 패키지
  • 모듈의 용량을 분석하여 효율적으로 모듈을 관리할 수 있도록 도와준다
  • npmjs : https://www.npmjs.com/package/webpack-bundle-analyzer

[ 예시 ]

  • 공통적으로 사용되는 외부 라이브러리의 chunk의 중복을 파악
  • webpackoptimization.splitChunks.chunks 로 중복 chunk 제거
  • ref : https://helloinyong.tistory.com/307

[ mode : production 설정 ]

[ 개요 ]

  • webpack.config.js > mode : production 설정
  • mode 옵션을 사용하여 phase에 필요한 webpack 내장 최적화 기능 사용 가능
  • 기본값은 mode : production
    (추가 정보 : https://webpack.kr/configuration/mode/)
  • mode 값을 설정하면 webpack v4부터 DefinePlugin을 사용하여 node 환경 변수값을 세팅해준다 (이전 포스팅 참조)

[ mode에 따른 기본 적용 플러그인 ]

  • mode : development : 디버깅 편의를 위한 적용
    • NamedChunkPlugin
    • NamedModulesPlugin
  • mode : production : JS 결과물을 최소화 하기 위한 적용
    • FlagDependencyUsagePlugin
    • FlagIncludedChunksPlugin
    • ModuleConcatenationPlugin
    • NoEmitOnErrorsPlugin
    • OccurenceOrderPlugin
    • SideEffectsFlagPlugin
    • TerserPlugin

[ 적용 ]

  • mode 파라미터를 이용한 설정
/* pakcage.json */
{
  ...
  "build": "webpack --progress --mode production"
}
  • 보통 phase별 개발환경을 구성할 때 DRY을 위해 공통 설정 파일각 phase별 설정 파일 별도로 구성
    • webpack.config.common.js : 공통 설정 파일
    • webpack.config.dev.js : 개발 phase 설정 파일
    • webpack.config.prod.js : 리얼 phase 설정 파일

[ optimization > minimize / minimizer ]

[ 개요 ]

  • optimization.minimize 옵션
    • TerserPlugin 또는 optimization.minimizer에 지정된 플러그인을
      사용하여 번들을 최소화 하는지 여부(true / false)
  • optimization.minimizer 옵션 : 하나 이상의 다른 최소화 도구 플러그인을 등록

[ 예시 ]

  • css-minimizer-webpack-plugin
    • CSS 파일 압축
  • terser-webpack-plugin
    • JS 난독화 / console 로그 제거 등
/* webpack.config.js */
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");

{
    ... // entry, output 
    optimization: {
      // minimize: true,
      minimizer: mode === 'production' ? [
        new CssMinimizerPlugin(), // CSS 압축
        new TerserPlugin({ // JS 난독화 등
          terserOptions: {
            compress: {
              drop_console: true // console.log 제거
            }
          }
        })
      ] : []
    }
}

[ splitChunks ]

[ 개요 ]

  • SplitChunksPlugin의 기본 동작과 추가 옵션을 지정
    : 여러개의 bundle 파일을 생성할 때 동일한 모듈의 chunk가 중복해서 각 번들 파일에 포함되는 것을 방지하기 위해 chunksplit하는 기능
  • Code Splitting 처럼 번들 결과를 여러개로 산출할 때, 각 청크간에 겹치는 패키지들을 별도의 파일로 추출한 벤더(vendor)를 만들어서 최적화를 수행할 수 있음

[ 예시 ]

/* webpack.config.js */
{
  //...
  optimization: {
    splitChunks: {
      // include all types of chunks
      chunks: 'all', // 'all' 'async' 'initial'
    },
  },
}
  • chunks
    • all : 동기 / 비동기로 import된 모든 모듈에 대한 최적화 진행
    • async : 비동기로 import된 모든 모듈에 대한 최적화 진행
    • initial : 정적(동기)으로 import 된 모듈에 대한 최적화 진행
    • 비교 설명 참조

[ externals ]

[ 개요 ]

  • externals 옵션을 이용해서 번들 대상에서 제외하여 최적화 하는 방법
  • 외부 라이브러리들은 이미 번들링된 파일이 있기 때문에 제외시킬 수 있다
  • copy-webpack-plugin 을 통해 externals에 지정한 라이브러리의 번들링 된 파일을 복사할 수 있도록 설정해야 한다

[ 예시 ]

const CopyPlugin = require("copy-webpack-plugin");

{
  ... // entry, output 등
    plugins: [
      new CopyPlugin([
          {
              from: "./node_modules/axios/dist/axios.min.js", // 외부 라이브러리의 번들파일 경로 지정
              to: "./axios.min.js" // 나의 dist/axios.min.js 생성
          }
      ])
  ],
    externals: { 
      axios: 'axios' // axios 제외
  },
}

[ Code Splitting / Dynamic import ]

[ Code Splitting ]

  • 개념
    • 코드를 다양한 기준으로 여러 번들로 분할하여 효율적인 리소스 로딩과 앱의 성능을 향상시키는 기술
  • 특징
    • 여러개의 번들 파일로 분할하여 브라우저의 다운로드 속도를 높힐 수 있다
    • lazy하게 사용자에게 fit한 리소스를 제공할 수 있다
    • 라이브러리 처럼 변동성이 적은 리소스의 캐싱으로 효율성을 향상
  • 방법
    • 1) entry 설정을 통한 수동 분할 : 개발자가 직접 entry를 별도로 구성해서 로직을 구성
    • 2) dynamic import : 동적으로 모듈을 import하는 코드를 사용 (권장)
    • ref : https://webpack.kr/guides/code-splitting/

[ Dynamic import ]

  • 예시
/* test.js 
  => chunkName을 webpack이 인식할 수 있도록 별도의 주석을 달아 줘야 한다 */
import(/* webpackChunkName: "result" */".result.js").then(m => {
  const result = m.default;
  const resultEl = document.createElement("div");
  resultEl.innerHTML = await result.render();
  document.body.appendChild(resultEl)
})
  • 결과
    • webpack.config.jsentry와 별도로 dynamic import가 사용된 파일은 별도로 번들 파일을 생성
profile
Developer & PhotoGrapher

0개의 댓글