コード分割で JavaScript ペイロードを削減

誰も待つのは好きではありません。読み込みに 3 秒以上かかると、50% を超えるユーザーがウェブサイトから離脱します

大きな JavaScript ペイロードを送信すると、サイトの速度に大きな影響を与えます。アプリケーションの最初のページが読み込まれたらすぐにすべての JavaScript をユーザーに送信するのではなく、バンドルを複数の部分に分割し、最初に必要なものだけを送信します。

コード分割が有益な理由

コード分割は、起動時間を最小限に抑えるための手法です。起動時に JavaScript を送信する量を減らすと、この重要な期間中のメインスレッドの作業を最小限に抑え、アプリケーションのインタラクティブ性を向上させることができます。

Core Web Vitals では、起動時にダウンロードされる JavaScript ペイロードを減らすと、Interaction to Next Paint(INP)時間が短縮されます。理由は、メインスレッドを解放することで、JavaScript の解析、コンパイル、実行に関連する起動コストを削減し、ユーザー入力により迅速に応答できるためです。

ウェブサイトのアーキテクチャによっては、特にウェブサイトがクライアントサイド レンダリングに大きく依存している場合は、マークアップのレンダリングに関連する JavaScript ペイロードのサイズを小さくすることで、Largest Contentful Paint(LCP)時間が短縮される可能性があります。これは、クライアントサイド マークアップの完了後に LCP リソースがブラウザによって検出されるまでに時間がかかる場合や、メインスレッドが忙しすぎてその LCP 要素をレンダリングできない場合に発生する可能性があります。どちらのシナリオでも、ページの LCP 時間が遅れる可能性があります。

測定

ページ上のすべての JavaScript の実行にかなりの時間がかかる場合は、Lighthouse で監査が失敗したことが示されます。

スクリプトの実行に時間がかかりすぎることを示す、失敗した Lighthouse 監査。

JavaScript バンドルを分割して、ユーザーがアプリを読み込むときに初期ルートに必要なコードのみを送信します。これにより、解析とコンパイルに必要なスクリプトの量が最小限に抑えられ、ページの読み込み時間が短縮されます。

webpackParcelRollup などの一般的なモジュール バンドラでは、動的インポートを使用してバンドルを分割できます。たとえば、次のコード スニペットは、フォームの送信時に呼び出される someFunction メソッドの例を示しています。

import moduleA from "library";

form.addEventListener("submit", e => {
  e.preventDefault();
  someFunction();
});

const someFunction = () => {
  // uses moduleA
}

ここで、someFunction は特定のライブラリからインポートされたモジュールを使用します。このモジュールが他の場所で使用されていない場合は、コードブロックを変更して、ユーザーがフォームを送信したときにのみ動的インポートを使用して取得するようにできます。

form.addEventListener("submit", e => {
  e.preventDefault();
  import('library.moduleA')
    .then(module => module.default) // using the default export
    .then(() => someFunction())
    .catch(handleError());
});

const someFunction = () => {
    // uses moduleA
}

モジュールを構成するコードは初期バンドルに含まれず、遅延読み込みされます。つまり、フォーム送信後に必要になった場合にのみユーザーに提供されます。ページのパフォーマンスをさらに改善するには、重要なチャンクをプリロードして優先度を付けてより早く取得します。

上のコード スニペットは単純な例ですが、サードパーティの依存関係を遅延読み込みすることは、大規模なアプリケーションでは一般的なパターンではありません。通常、サードパーティの依存関係は、頻繁に更新されないため、キャッシュに保存できる別のベンダー バンドルに分割されます。SplitChunksPlugin がどのように役立つかについては、こちらをご覧ください。

クライアントサイド フレームワークを使用する場合は、ルートまたはコンポーネント レベルで分割するのが、アプリケーションのさまざまな部分を遅延読み込みする簡単な方法です。webpack を使用する一般的なフレームワークの多くは、構成に直接関与するよりも簡単に遅延読み込みを実現できる抽象化を提供しています。