コード分割で 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 を使用する多くの一般的なフレームワークは、構成を自分で掘り下げるよりも遅延読み込みを簡単にする抽象化を提供します。