【webpack】bundleサイズを40%減らしてJavaScriptビルドも40%高速化する方法

https://cdn-ak.f.st-hatena.com/images/fotolife/c/commmune/20191219/20191219082134.png

Moment.jsのLocaleがでかすぎる問題

Webpack Bundle Analyzer という解析ツールがあります。まだ使っていないエンジニアの方は早急に npm i しましょう。チューニングのバイブルです。

(before)Memont.jsのlocaleが大きすぎる

ご覧の通り、localesだけで300 kBくらいを占めています。

この由々しき問題は公式も把握しており バンドルからlocalesを省く方法 を説明してくれています。これにならって moment-locales-webpack-pluginnpm i しましょう。

Next.jsをお使いの方は↓

    webpack: (config, _options) => {
      config.plugins.push(new MomentLocalesPlugin())
      return config
    }

これだけで 300 kB バンドルサイズをまるまる小さくできます。

webpackのsplitChunkをもっと賢く

Next.js というReact.jsフレームワークがあります。まだお使いでないエンジニアの方は早急に乗り換えましょう。React界隈のバイブルです。

複数のchunkで同じnpmパッケージを重複参照してしまう という問題自体はwebpack+SPA構成であれば他フレームワークでも再現するかもしれません。

例えば Lodash を全ページで使用する場合下記の問題が起こりえます。

理想

common.chunk.js のような全ページ共通のchunkに吐き出してほしい

現実

pageA.chunk.js pageB.chunk.js pageC.chunk.js 各々にLodashが含まれてしまう

splitChunksの設定 splitChunks.minChunks で解決可能かもしれませんが、Next.jsも同様に取り組んでいます。まだ試験的な機能ですが

module.exports = {
  experimental: {
    granularChunks: true
  }
}

とビルド設定に加えると(ある程度)重複を排除してバンドルしてくれます。神。
この設定だけでさらに 150 kB バンドルサイズが削減できます。

before --> after

940 kB --> 555 kB (非gzip時のメインJSファイル)

(after)各chunkでMoment.jsが占める割合が小さくなった

41%バンドルサイズを削減できました。当然ビルド時間が比例して短縮できるので開発生産性アップにも繋がり、一石二鳥です。