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

待っているのが嫌な人はいません。読み込みに 3 秒以上かかると、ユーザーの 50% 以上がウェブサイトを離れます

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

コード分割が役立つ理由

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

Core Web Vitals については、起動時にダウンロードされる JavaScript ペイロードを削減すると、First Input Delay(FID)Interaction to Next Paint(INP)の時間が改善されます。その理由は、メインスレッドを解放することで、アプリケーションが JavaScript の解析、コンパイル、実行に関連する起動費用を削減し、ユーザー入力により迅速に応答できるようになることです。

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

測定

Lighthouse では、ページ上のすべての JavaScript の実行にかなりの時間がかかると、不合格の監査が表示されます。

スクリプトの実行に時間がかかりすぎていることを示す、失敗した 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 を使用する一般的なフレームワークの多くは抽象化機能を備えており、自分で構成を詳しく調べるよりも遅延読み込みを簡単に行うことができます。