Webpack でパフォーマンス バジェットを設定する

Webpack は、インポートされたすべてのファイルを結合し、バンドルと呼ばれる 1 つ以上の出力ファイルにパッケージ化します。バンドルは便利ですが、アプリが大きくなるとバンドルも大きくなります。バンドル サイズが大きくなりすぎて、アプリケーションの読み込み時間に影響しないように、バンドル サイズをモニタリングする必要があります。Webpack は、アセットサイズに基づいてパフォーマンス バジェットを設定することをサポートしており、バンドルサイズを監視できます。

実際に動作する例として、新年までの日数をカウントするアプリを次に示します。これは Reactmoment.js で構築されています。(実際のアプリがフレームワークやライブラリにますます依存しているのと同じです。😉)

元日まであと何日かをカウントするアプリ

測定

この Codelab には、webpack でバンドルされたアプリがすでに含まれています。

  1. [Remix to Edit] をクリックして、プロジェクトを編集可能にします。
  2. [ターミナル] をクリックします(注: [ターミナル] ボタンが表示されない場合は、[全画面表示] オプションを使用する必要があります)。
  3. アセットとそのサイズのカラーコード化されたリストを取得するには、コンソールに webpack と入力します。
webpack

メインバンドルは 244 KiB(250 KB)より大きいため、黄色でハイライト表示されています。

Webpack の出力。バンドルサイズが 323 KiB と表示されている
JS バンドルが大きすぎることを警告する webpack ⚠️

これらの警告は、プロダクション モードでデフォルトで有効になっており、アセットとエントリ ポイント(ページの初回読み込み時に使用されるすべてのアセットの組み合わせ)の両方で、デフォルトのしきい値は圧縮されていない 244 KiB です。

アセットが推奨サイズの上限を超えていることを示す Webpack の警告
JS バンドルが大きすぎることを警告する webpack ⚠️

Webpack は警告を出すだけでなく、バンドルを縮小する方法に関する推奨事項も提示します。推奨される手法について詳しくは、Web Fundamentals をご覧ください。

Webpack のパフォーマンス最適化に関する推奨事項
webpack のパフォーマンス最適化に関する推奨事項 💁

カスタムのパフォーマンス予算を設定する

適切なパフォーマンス予算は、プロジェクトの性質によって異なります。ご自身で調査することをおすすめします。目安として、圧縮/最小化されたクリティカル パス リソースを 1 分あたり 170 KB 未満で配信することをおすすめします。

このシンプルなデモでは、さらに保守的に 100 KB(97.7 KiB)に設定してみましょう。webpack.config.js に以下を追加します。

module.exports = {
  //...
  performance: {
    maxAssetSize: 100000,
    maxEntrypointSize: 100000,
    hints: "warning"
  }
};

新しいパフォーマンス バジェットはバイト単位で設定されます。

  • 個々のアセットの 100,000 バイト(maxAssetSize)
  • エントリ ポイントの 100,000 バイト(maxEntrypointSize)

この場合、エントリ ポイントとしても機能するバンドルは 1 つだけです。

hints に指定できる値は次のとおりです。

  1. warning(デフォルト): 黄色の警告メッセージが表示されますが、ビルドはパスします。これは開発環境で使用することをおすすめします。
  2. error: 赤色のエラー メッセージが表示されますが、ビルドは合格します。この設定は、本番環境ビルドに推奨されます。
  3. false: 警告やエラーは表示されません。
Webpack のパフォーマンス エラー(赤いフォント)
Webpack のパフォーマンス ヒント「エラー」🚨

最適化

パフォーマンス バジェットの目的は、パフォーマンスの問題が修正困難になる前に警告することです。アプリの構築方法は常に複数あり、手法によっては読み込み時間を短縮できます。(その多くは、JavaScript の最適化で説明されています。🤓)

フレームワークとライブラリはデベロッパーの作業を楽にしますが、エンドユーザーはアプリの構築方法を気にしません。アプリが機能的で高速であればよいのです。パフォーマンス バジェットを超過している場合は、最適化を検討するタイミングです。

実際には、大規模なクライアントサイド フレームワークを簡単に置き換えることは難しいため、賢く使用することが重要です。少し調べれば、人気のあるライブラリの代替となる、同じように機能するサイズの小さいライブラリが見つかることがよくあります(date-fnsmoment.js の優れた代替手段です)。パフォーマンスに大きな影響がある場合は、フレームワークやライブラリをまったく使用しない方がよいこともあります。

不要なコードを削除することは、大きなサードパーティ ライブラリを含むアプリを最適化するうえで有効な方法です。未使用のコードを削除するガイドでこのプロセスについて詳しく説明しています。ここでは、moment.js を使用せずにカウントダウン コードを書き換える簡単な方法を紹介します。

app/components/Countdown.jsx で、以下を削除します。

const today = moment();
const yearEnd = moment().endOf('year');
const daysLeft = yearEnd.diff(today, 'days');

次の行を削除します。

const moment = require('moment');

少し計算が必要ですが、バニラ JavaScript で同じカウントダウンを実装できます。

const today = new Date();
const year = today.getFullYear();
const yearEnd = new Date(year,11,31); //months are zero indexed in JS
const timeDiff = Math.abs(yearEnd.getTime() - today.getTime());
const daysLeft = Math.ceil(timeDiff / (1000 * 3600 * 24));

次に、package.json から moment.js を削除し、コンソールで webpack を再度実行して、最適化されたバンドルをビルドします。

じゃーん!223 KiB(230 KB)削減され、アプリは予算内に収まりました。🎉

最適化後の Webpack バンドル サイズの出力は 97.7 KiB

モニタリング

webpack でパフォーマンス予算を設定するには、数行のコードを追加するだけで済みます。大きな依存関係を(誤って)追加した場合は、警告が表示されます。「見えなければ気にならない」という言葉がありますが、webpack を使用すると、パフォーマンスへの影響を常に把握できます。