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

誰も待つのは好きではありません。 50% 以上のユーザーが、ウェブサイトの読み込みにかかる時間が 3 秒を超えるとその閲覧をやめてしまいます

大きな 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 を使用する一般的なフレームワークの多くは、構成に直接関与するよりも簡単に遅延読み込みを実現できる抽象化を提供しています。