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

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

実際の動作を確認するには、新年までの残り日数をカウントするアプリを使用します。 これは Reactmoment.js で構築されています。(フレームワークやライブラリにますます依存する実際のアプリがそうであるように、😉)

元日までの残り日数をカウントするアプリ

測定

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

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

メインバンドルは 244 KiB(250 KB)を超えているため、黄色でハイライト表示されます。

バンドルサイズが 323 KiB であることを示す Webpack の出力
Webpack が大量の JS バンドルについて警告する ⚠️

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

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

Webpack は警告だけでなく、バンドルのサイズを縮小する方法についての推奨事項も提供します。推奨される手法については、ウェブの基礎をご覧ください。

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

カスタム パフォーマンス バジェットの設定

適切なパフォーマンス バジェットは、プロジェクトの性質によって異なります。常に独自に調査することをおすすめします。経験則として、圧縮/圧縮されたクリティカル パス リソースは 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 つだけです。

ヒントに指定できる値は次のとおりです。

  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');

少々計算が必要ですが、同じカウントダウンを vanilla 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 を使用すれば、パフォーマンスへの影響を常に認識できます。