スクリプトが必要になるまで遅延させる

IntersectionObserverとユーザーインタラクションのトリガーを使用して、オンデマンドでJavaScriptを読み込む

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-05

スクリプトが必要になるまで遅延させる

2025 Web Almanacによると、モバイルページの中央値では251 KBの未使用のJavaScriptが送信されている。これは、訪問者が必要とする前にブラウザがダウンロード、解析、コンパイルするJavaScriptである。誰もクリックしていないフォーム。誰も開いていないチャットウィジェット。ファーストビュー(アバブ・ザ・フォルド)の下にあるマップの統合。そのすべてが、ページ読み込みの最も重要な段階で帯域幅とCPU時間を奪い合っている。

これに対処する最も効果的な方法は、実際に必要になるまでスクリプトを読み込まないことである。これは、scriptタグでasyncまたはdefer属性を使用するのとは異なる。これらの属性は、ページ読み込み中にスクリプトをダウンロードし、実行のタイミングを変更するだけである。オンデマンド読み込みでは、トリガーが発火するまでスクリプトを一切ダウンロードしない。

最終レビュー: 2026年3月 Arjen Karel

我々は長い間、画像に対してこれを行ってきた。これはレイジーローディング(遅延読み込み)と呼ばれている。レイジーローディングでは、ファーストビューの下にある画像は、スクロールして表示される直前に読み込まれる。ブラウザは、実際に必要なもののダウンロード、解析、描画にリソースを費やすことができる。同じ原則がJavaScriptにも適用され、これによりLighthouseの警告「reduce unused JavaScript」が解決され、Interaction to Next Paint (INP)などの応答性指標が改善される。

残念ながら、画像にloading="lazy"を追加するほど単純ではないが、小さなヘルパー関数とトリガーを使用すれば機能させることができる。

スクリプト注入ヘルパー

ページ読み込み後にスクリプトをページに追加するには、script要素を作成してドキュメントのheadに追加する小さな関数が必要である。

function injectScript(scriptUrl, callback) {
    const script = document.createElement('script');
    script.src = scriptUrl;
    if (typeof callback === 'function') {
        script.onload = callback;
    }
    document.head.appendChild(script);
}

scriptUrlパラメータは、読み込むスクリプトのURLである。オプションのcallback関数は、スクリプトの読み込みが完了した後に実行される。これは、Google Maps APIを読み込んだ後にinitMap()を呼び出すなど、初期化が必要なスクリプトにとって重要である。

オンデマンド読み込みのトリガー

注入ヘルパーの準備ができたら、トリガーが必要である。信頼性の高い方法は2つある。要素がスクロールして表示されたときに読み込む方法と、ユーザーが要素とインタラクションしたときに読み込む方法である。

IntersectionObserver: 表示されたときに読み込む

IntersectionObserverは、要素がビューポートに入ったときに発火する。これは、マップコンテナ、コメントセクション、ファーストビューの下にある埋め込みウィジェットなど、ページの特定のセクションに関連付けられたスクリプトに最適なトリガーである。

function injectScriptOnIntersection(scriptUrl, elementSelector, callback) {
    const element = document.querySelector(elementSelector);
    const observer = new IntersectionObserver((entries, obs) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                injectScript(scriptUrl, callback);
                obs.unobserve(entry.target);
            }
        });
    });
    observer.observe(element);
}

この関数は、スクリプトのURL、読み込みのトリガーとなる要素のCSSセレクタ、および初期化のためのオプションのコールバックを受け取る。要素がスクロールして表示されると、スクリプトが注入され、オブザーバーは監視を解除する。

// マップコンテナがスクロールして表示されたときにGoogle Maps APIを読み込む
injectScriptOnIntersection(
    'https://maps.googleapis.com/maps/api/js?key=YOUR_KEY',
    '#map-container',
    () => initMap()
);

IntersectionObserverはすべてのモダンブラウザでサポートされている(Can I Useによると世界で95.76%の普及率)。ポリフィルは必要ない。

インタラクション時: ユーザーの操作時に読み込む

最も効果的な方法は、訪問者がそれを必要とする要素と実際にインタラクションしたときにのみスクリプトを読み込むことである。チャットウィジェットは、誰かがチャットボタンをクリックするまで読み込む必要はない。フォームバリデーションライブラリは、ユーザーがフォームフィールドにフォーカスするまで読み込む必要はない。

function injectScriptOnInteraction(scriptUrl, elementSelector, eventTypes, callback) {
    const element = document.querySelector(elementSelector);
    const handler = () => {
        eventTypes.forEach(type => element.removeEventListener(type, handler));
        injectScript(scriptUrl, callback);
    };
    eventTypes.forEach(type => {
        element.addEventListener(type, handler);
    });
}

この関数は、ターゲット要素の指定されたイベントをリッスンする。最初のイベント発生時にすべてのリスナーを削除し、スクリプトを注入する。この方法の利点は、訪問者が要素と一度もインタラクションしなかった場合、スクリプトがまったく読み込まれないことである。

// チャットボタンがクリックまたはホバーされたときにチャットウィジェットのスクリプトを読み込む
injectScriptOnInteraction(
    'chat-widget.js',
    '#chat-button',
    ['click', 'mouseover', 'touchstart'],
    () => initChat()
);

実際の効果

このパターンは、初期ページ読み込み時に必要のないあらゆるスクリプトで機能する。一般的なユースケースは以下の通りである。

  • チャットウィジェット: 一般的なチャットウィジェットは200〜400 KBのJavaScriptを読み込む。PostmarkがIntercomウィジェットを遅延させ、即時ではなくクリック時に読み込むようにしたところ、Time to Interactiveは7.7秒から3.7秒に短縮された。
  • 動画の埋め込み: YouTubeの埋め込みは1 MB以上のデータを読み込む。再生ボタン付きのサムネイルを表示し、クリック時に埋め込みを読み込むようにする。
  • マップの統合: Google Mapsは数百キロバイトのJavaScriptを読み込む。IntersectionObserverを使用して、マップコンテナがスクロールして表示されたときに読み込むようにする。
  • アナリティクスとトラッキング: アナリティクススクリプトは、最初のユーザーインタラクションが発生する後まで待機できる。ヒートマップツールの記録開始がページ読み込みの3秒後になったとしても、誰もがっかりすることはない。
  • フォームライブラリ: バリデーションライブラリ、日付ピッカー、リッチテキストエディタは、ユーザーがフォームにフォーカスしたときに読み込むことができる。

遅延させるべきではない場合

すべてのスクリプトを遅延させるべきというわけではない。スクリプトがファーストビューのコンテンツのレンダリングを担っている場合、それを遅延させるとLargest Contentful Paintは改善するどころか悪化してしまう。ヘッダーナビゲーションを初期化したり、ヒーローセクションをレンダリングしたり、重要なA/Bテストのバリエーションを設定したりするスクリプトは、早期に実行する必要がある。

ルールはシンプルである。訪問者が最初のビューポート内でスクリプトが生成するものを見たりインタラクションしたりする場合は、通常通り読み込む。スクリプトがファーストビューの下にあるものや、ユーザーアクションの背後にあるものを動作させる場合は、上記のパターンのいずれかを使用して遅延させる。

Tip: JavaScriptのすべての読み込み戦略の完全な概要については、JavaScriptを遅延またはスケジュールするための16の方法を参照。

改善の測定

2025 Web Almanacの報告によると、モバイルにおけるTotal Blocking Timeの中央値は1,916ミリ秒で、2024年から58%増加している。そのブロッキングの大部分は、ページ読み込み時に実行する必要のなかったJavaScriptによるものである。重要でないスクリプトを遅延させることで、それらをクリティカルパスから完全に取り除くことができる。

オンデマンド読み込みを実装した後は、Real User Monitoringで改善を確認してほしい。Lighthouseだけでなく、フィールドデータでINPスコアとTotal Blocking Timeをチェックすること。ラボテストはキャッシュが空の高速なマシンで実行される。しかし訪問者は、ブラウザのタブを15個開いた状態でモバイルネットワークを利用している。そこにこそ違いが表れるのである。

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

何が本当に遅いのか、見つけ出します。

フィールドデータでCritical Rendering Pathをマッピング。Lighthouseレポートではなく、優先順位付きの修正リストをお渡しします。

監査を依頼する
スクリプトが必要になるまで遅延させるCore Web Vitals スクリプトが必要になるまで遅延させる