今後のナビゲーションを高速化するためにリソースをプリフェッチする

rel=prefetch リソースヒントとその使用方法について学びます。

公開日: 2019 年 9 月 12 日、最終更新日: 2025 年 2 月 8 日

調査によると、読み込み時間が短くなるとコンバージョン率が高まり、ユーザー エクスペリエンスが向上します。ユーザーがウェブサイトをどのように移動し、次にどのページにアクセスする可能性が高いかを把握している場合は、それらのページのリソースを事前にダウンロードすることで、今後のナビゲーションの読み込み時間を短縮できます。

このガイドでは、プリフェッチを効率的に実装できる <link rel=prefetch> を使用して、この目標を達成する方法について説明します。

rel=prefetch でサイトのパフォーマンスを改善する

ウェブページに <link rel=prefetch> を追加すると、ユーザーが今後必要とする可能性のあるリソース(スクリプトや CSS ファイルなど)をブラウザにダウンロードするよう指示します。

<link rel="prefetch" href="/css/styles.css">

prefetch ヒントは、すぐに必要でないリソースに余分なバイト数を消費するため、この手法は慎重に適用する必要があります。ユーザーが必要とするリソースのみをプリフェッチしてください。ユーザーが低速な接続を使用している場合は、プリフェッチを行わないことを検討してください。これは Network Information API で検出できます。

ユースケース

プリフェッチには、リソースを事前にダウンロードしてウェブページの速度を上げる多くのユースケースがあります。

後続のページをプリフェッチする

後続のページが予測可能な場合は HTML ドキュメントをプリフェッチし、リンクをクリックしたときにページが即座に読み込まれるようにします。

たとえば、商品リスティング ページでは、リスト内の最も人気のある商品のページをプリフェッチできます。次のナビゲーションを予測しやすい場合もあります。たとえば、ショッピング カート ページでは、ユーザーが購入手続きページにアクセスする可能性が高いため、プリフェッチの候補として適しています。

リソースのプリフェッチでは追加の帯域幅が使用されますが、ほとんどのパフォーマンス指標を改善できます。ドキュメント リクエストがキャッシュヒットすると、最初のバイトまでの時間(TTFB)は大幅に短縮されます。TTFB が短くなるため、Largest Contentful Paint(LCP)First Contentful Paint(FCP)など、その後の時間ベースの指標も短くなることがよくあります。

静的アセットをプリフェッチする

ユーザーがアクセスする可能性のある後続のセクションを予測できる場合は、スクリプトやスタイルシートなどの静的アセットをプリフェッチします。これは、これらのアセットが複数のページで共有される場合に特に便利です。

たとえば、Netflix は、ユーザーがログアウトしたページに滞在している時間を利用し、ユーザーがログインしたときに使用される React をプリフェッチします。これにより、今後のナビゲーションの Time to Interactive を 30% 短縮できました。

静的アセットのプリフェッチがパフォーマンス指標に与える影響は、プリフェッチされるリソースによって異なります。

  • 画像をプリフェッチすると、LCP 画像要素の LCP 時間を大幅に短縮できます。
  • スタイルシートをプリフェッチすると、スタイルシートのダウンロードにかかるネットワーク時間が不要になるため、FCP と LCP の両方を改善できます。スタイルシートはレンダリングをブロックするため、プリフェッチすると LCP が低下する可能性があります。次のページの LCP 要素が background-image プロパティを使用してリクエストされた CSS 背景画像の場合、その画像もプリロードされたスタイルシートの依存リソースとしてプリフェッチされます。
  • JavaScript をプリフェッチすると、ナビゲーション中にネットワークから最初にフェッチする必要がある場合よりも、プリフェッチされたスクリプトの処理をはるかに早く行うことができます。これにより、ページの Interaction to Next Paint(INP)に影響する可能性があります。マークアップが JavaScript を使用してクライアント上でレンダリングされる場合、リソース読み込みの遅延を短縮することで LCP を改善できます。また、ページの LCP 要素を含むマークアップのクライアントサイド レンダリングをより早く行うことができます。
  • 現在のページでまだ使用されていないウェブフォントをプリフェッチすると、レイアウトのずれを解消できます。font-display: swap; が使用されている場合、フォントのスワップ期間が不要になるため、テキストのレンダリングが高速化され、レイアウト シフトが解消されます。プリフェッチされたフォントが後続のページで使用され、そのページの LCP 要素がウェブフォントを使用したテキスト ブロックである場合、その要素の LCP も速くなります。

オンデマンドの JavaScript チャンクをプリフェッチする

JavaScript バンドルをコード分割すると、最初にアプリの一部のみを読み込み、残りは遅延読み込みできます。この手法を使用する場合は、すぐに必要ではないが、近い将来リクエストされる可能性が高いルートまたはコンポーネントにプリフェッチを適用できます。

たとえば、絵文字選択ツールを含むダイアログを開くボタンを含むページがある場合、そのページを home、dialog、picker の 3 つの JavaScript チャンクに分割できます。ホームとダイアログは最初に読み込み、選択ツールはオンデマンドで読み込むことができます。webpack などのツールを使用すると、これらのオンデマンド チャンクをプリフェッチするようにブラウザに指示できます。

rel=prefetch の実装方法

prefetch を実装する最も簡単な方法は、ドキュメントの <head><link> タグを追加することです。

<head>
  ...
  <link rel="prefetch" href="//css/styles.css">
  ...
</head>

Link HTTP ヘッダーを使用してプリフェッチを開始することもできます。

Link: </css/style.css>; rel=prefetch

HTTP ヘッダーでプリフェッチ ヒントを指定すると、ブラウザがリソース ヒントを探すためにドキュメントを解析する必要がなくなるため、場合によってはパフォーマンスがわずかに向上します。

Webpack マジック コメントを使用して JavaScript モジュールをプリフェッチする

webpack を使用すると、ユーザーがすぐにアクセスまたは使用する可能性が高いルートまたは関数のスクリプトをプリフェッチできます。

次のコード スニペットは、lodash ライブラリから並べ替え関数を遅延読み込みして、フォームから送信される一連の数値を並べ替えます。

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

この関数を読み込むために「送信」イベントが発生するのを待つのではなく、このリソースをプリフェッチして、ユーザーがフォームを送信するまでにキャッシュに保存される可能性を高めることができます。webpack では、import() 内でマジック コメントを使用してこれを実現できます。

form.addEventListener("submit", e => {
   e.preventDefault()
   import(/* webpackPrefetch: true */ 'lodash.sortby')
         .then(module => module.default)
         .then(sortInput())
         .catch(err => { alert(err) });
});

これにより、webpack は <link rel="prefetch"> タグを HTML ドキュメントに挿入します。

<link rel="prefetch" href="1.bundle.js">

オンデマンド チャンクのプリフェッチによるパフォーマンス上のメリットは微妙ですが、一般に、オンデマンド チャンクがすぐに利用可能になるため、オンデマンド チャンクに依存するインタラクションへのレスポンスが速くなることが期待できます。インタラクションの性質によっては、ページの INP にメリットをもたらす可能性があります。

一般に、プリフェッチは全体的なリソースの優先順位付けにも影響します。リソースのプリフェッチは、可能な限り低い優先度で実行されます。したがって、プリフェッチされたリソースは、現在のページに必要なリソースの帯域幅を競合しません。

prefetch を内部で使用するライブラリを使用して、よりスマートなプリフェッチを実装することもできます。

  • quicklinkIntersection Observer API を使用して、リンクがビューポートに表示されたタイミングを検出し、アイドル状態中にリンクされたリソースをプリフェッチします。ボーナス: クイックリンクの重量は 1 KB 未満です。
  • Guess.js は、アナリティクス レポートを使用して予測モデルを構築し、ユーザーが必要とする可能性が高いコンテンツのみをスマートにプリフェッチします。

quicklink と Guess.js はどちらも Network Information API を使用して、ユーザーが低速なネットワークを使用している場合や Save-Data がオンになっている場合にプリフェッチを回避します。

プリフェッチの仕組み

リソースヒントは必須の指示ではなく、実行するかどうか、実行するタイミングはブラウザによって異なります。

プリフェッチは同じページで複数回使用できます。ブラウザはすべてのヒントをキューに追加し、アイドル状態のときに各リソースをリクエストします。Chrome では、プリフェッチの読み込みが完了しておらず、ユーザーが目的のプリフェッチ リソースに移動した場合、ブラウザによって、進行中の読み込みがナビゲーションとして認識されます(他のブラウザ ベンダーでは、この実装が異なる場合があります)。

プリフェッチは「低」優先度で行われるため、プリフェッチされたリソースは、現在のページで必要なリソースと帯域幅を競合しません。

プリフェッチされたファイルは、リソースがキャッシュに保存可能な場合は HTTP キャッシュに保存されます。それ以外の場合は破棄され、使用されません。

まとめ

prefetch を使用すると、今後必要となるリソースを事前にダウンロードすることで、サイトのウェブ パフォーマンスを大幅に改善できます。prefetch は、ほとんどの最新のブラウザでサポートされています。この手法では、使用されない可能性のある追加バイトの読み込みが必要になるため、使用時には注意が必要です。必要な場合にのみ使用し、高速なネットワークでのみ使用することをおすすめします。