LoginSignup
12
8

More than 3 years have passed since last update.

React Bundle.js の最小化

Posted at

はじめに

本編は、webpackTypeScript を使用する前提になってます。React に限らず、他のSPAにも適用できます。

なぜ最小化が必要

複数のライブラリ使うと、ビルド後の bundle.min.js も膨大(10mb↑)になって、ユーザの初期ロード時間が長くなります。ネットワーク弱者は、表示できない可能性もあります。

どんな方法があるの

  • 必要だけの importにしましょう
  • Chunks しましょう
  • Compession しましょう
  • Content-type: gzip にしましょう

具体的にどうすれの?

これから色んなツールを駆使し、サイズを減りましょう

まずは分析

bundle.js の内部構造を分析し、大きいサイズのライブラリから、減らして行きます。
最初に登場するのは、webpack-bundle-analyzer です。

bundle.min.js の内部構造を図面化してくれるツールです。大体こんな感じ
93f72404-b338-11e6-92d4-9a365550a701.gif

webpack

import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';

const configs: Configuration = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
};

export default configs;

次は、stats.jsonです。
バンドルされたライブラリの内部、jsonファイル使った場合、圧縮されませんため、stats.jsonから分析します。下記コマンドから作成できます。

stats.json
webpack --config webpack.prod.ts --profile --json > stats.json

次はライブラリ構造の調査

先の分析結果を元に、割合が大きいのライブラリから調査する、今回は lodash.js を対象にします。node_modules にライブラリのソース確認できますので、ちょっとのぞきましょう。

lodash
   | - isNull.js
   | - map.js
   | - math.js
   | - min.js

上記構造から、このライブラリは複数ファイルに分散されることが分かりました。必要の分だけimportします。

改善方法
- import * as _ from 'lodash';
+ import map from 'lodash/map';

stats.json の調査

webpack-bundle-analyzer結果に、大きいなjsonブロックがなければ、調査しなくても大丈夫です。典型的のは、momentです。下記リンクからlatest.jsonを検索すれば、詳しく書いてます。

webpackのbundle後のJavaScriptのサイズを減らしている話

Chunks を有効にする

Code Splitting 手法の1つ、その他の色々ありますので、リンク先を見てください。有効する方法は簡単なので、下記設定を参考してください。
https://webpack.js.org/guides/code-splitting/

webpack
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';

const configs: Configuration = {
  optimization: {
    splitChunks: {
      name: true,
      cacheGroups: {
        commons: {
          chunks: 'initial',
          minChunks: 2
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          chunks: 'all',
          priority: -10
        }
      }
    },
    runtimeChunk: true
  },
};

export default configs;

圧縮機能を有効にする

compression-webpack-pluginの登場です。ビルド同時に、圧縮されたファイルも出力される。
node-zopfliを使えば、もっと圧縮率を上げられます。

webpack
import CompressionPlugin from 'compression-webpack-plugin';
import zopfli from 'node-zopfli';

const configs: Configuration = {
  plugins: [
    new CompressionPlugin({
      test: /\.js$/,
      filename: '[path].gz[query]',
      algorithm: (source, compressionOptions, callback) => {
        return zopfli.gzip(Buffer.from(source), compressionOptions, callback);
      }
    })
  ]
};

export default configs;

最後は、Content-type 設定しましょう

圧縮されるファイルは、そのまま使えませんので、サーバ上、gzip配信機能の有効が必要です。

まとめ

dynamic importloadable componentも、サイズ最小化の有効手段なので、是非使ってみてください。

12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8