公開日: 2022 年 12 月 2 日、最終更新日: 2026 年 10 月 29 日
Chrome チームは、ユーザーが次に移動する可能性が高いページの完全な事前レンダリングを復活させました。
事前レンダリングの簡単な歴史
以前、Chrome は <link rel="prerender" href="/next-page"> リソースヒントをサポートしていましたが、Chrome 以外では広くサポートされておらず、表現力の高い API ではありませんでした。
リンク rel=prerender ヒントを使用するこの従来の事前レンダリングは、NoState Prefetch の導入に伴い非推奨となりました。NoState Prefetch は、将来のページに必要なリソースを取得するものの、ページの完全な事前レンダリングや JavaScript の実行は行いません。NoState Prefetch は、リソースの読み込みを改善することでページ パフォーマンスを向上させますが、完全な事前レンダリングのようにページ読み込みを瞬時に行うことはできません。
Chrome チームは、完全な事前レンダリングを Chrome に再導入しました。既存の使用方法との競合を回避し、将来的に事前レンダリングを拡張できるようにするため、この新しい事前レンダリング メカニズムでは <link rel="prerender"...> 構文を使用しません。この構文は NoState Prefetch 用にそのまま残され、将来的に廃止される予定です。
ページが事前レンダリングされる仕組み
ページを事前レンダリングする方法は 4 つあり、いずれもナビゲーションを高速化することを目的としています。
- Chrome のアドレスバー(「オムニボックス」とも呼ばれます)に URL を入力すると、Chrome は、過去の閲覧履歴に基づいて、ユーザーがそのページにアクセスする可能性が高いと判断した場合、ページを自動的に事前レンダリングすることがあります。
- ブックマーク バーを使用している場合、ブックマーク ボタンのいずれかにポインタを合わせると、Chrome が自動的にページを事前レンダリングすることがあります。
- Chrome のアドレスバーに検索キーワードを入力すると、検索エンジンからの指示に応じて、検索結果ページが自動的に事前レンダリングされることがあります。
- サイトは Speculation Rules API を使用して、事前レンダリングするページをプログラムで Chrome に指示できます。これは、
<link rel="prerender"...>が行っていた処理に代わるもので、サイトはページ上の投機ルールに基づいてページを事前にプリレンダリングできます。これらの要素は、ページ上に静的に存在することも、ページ所有者が適切と判断した JavaScript によって動的に挿入されることもあります。
いずれの場合も、事前レンダリングは、ページが非表示のバックグラウンド タブで開かれたかのように動作し、フォアグラウンド タブを事前レンダリングされたページに置き換えることで「有効化」されます。完全に事前レンダリングされる前にページが有効化された場合、そのページの現在の状態は「フォアグラウンド」になり、読み込みが続行されます。つまり、依然として有利なスタートを切ることができます。
事前レンダリングされたページは非表示の状態で開かれるため、煩わしい動作を引き起こす多くの API(プロンプトなど)はこの状態では有効にならず、ページが有効になるまで遅延されます。これがまだ不可能な少数のケースでは、事前レンダリングはキャンセルされます。Chrome チームは、プリレンダリングのキャンセルの理由を API として公開し、DevTools の機能を強化して、このようなエッジケースを簡単に特定できるように取り組んでいます。
事前レンダリングの影響
次の動画に示すように、事前レンダリングにより、ページがほぼ瞬時に読み込まれます。
このサンプルサイトはすでに高速なサイトですが、それでもプリレンダリングによってユーザー エクスペリエンスが向上することがわかります。そのため、サイトの Core Web Vitals にも直接的な影響を及ぼす可能性があります。LCP はほぼゼロになり、CLS は減少し(読み込み CLS は最初のビューの前に発生するため)、INP は改善されます(読み込みはユーザーが操作する前に完了するため)。
ページが完全に読み込まれる前に有効化された場合でも、ページの読み込みを先に開始することで、読み込みエクスペリエンスが向上します。事前レンダリングの実行中にリンクが有効になると、事前レンダリング ページがメインフレームに移動し、読み込みが続行されます。
ただし、プリレンダリングでは追加のメモリとネットワーク帯域幅が使用されます。ユーザーのリソースを消費して過剰な事前レンダリングを行わないように注意してください。ページに移動する可能性が高い場合にのみ、事前レンダリングを行います。
アナリティクスで実際のパフォーマンスへの影響を測定する方法について詳しくは、パフォーマンスの測定のセクションをご覧ください。
Chrome のアドレスバーの予測を表示する
1 つ目のユースケースでは、chrome://predictors ページで URL の Chrome の予測を表示できます。
緑色の線は、プリレンダリングをトリガーするのに十分な信頼度があることを示します。この例では、「s」と入力すると、ある程度の信頼度(黄色)が得られますが、「sh」と入力すると、Chrome は https://sheets.google.com に移動する可能性が非常に高いと判断します。
このスクリーンショットは、比較的最近インストールされた Chrome で、信頼度ゼロの予測を除外して撮影されたものですが、独自の予測機能を表示すると、かなり多くのエントリが表示され、十分な信頼度レベルに達するために必要な文字数が増える可能性があります。
これらの予測機能は、アドレスバーに表示される候補の表示にも使用されています。
Chrome は、ユーザーの入力と選択に基づいて予測機能を継続的に更新します。
- 信頼度が 30% を超える場合(オレンジ色で表示)、Chrome はドメインに事前に接続しますが、ページを事前レンダリングしません。
- 信頼度が 50% を超える場合(緑色で表示)、Chrome は URL を事前レンダリングします。
Speculation Rules API
Speculation Rules API のプリレンダリング オプションでは、ウェブ デベロッパーがページに JSON 命令を挿入して、プリレンダリングする URL をブラウザに通知できます。
URL リスト
投機ルールは、URL のリストに基づいて設定できます。
<script type="speculationrules">
{
"prerender": [{
"urls": ["next.html", "next2.html"]
}]
}
</script>
ドキュメント ルール
投機ルールは、where 構文を使用した「ドキュメント ルール」にすることもできます。これは、href セレクタ(URL パターン API に基づく)または CSS セレクタに基づいて、ドキュメント内で見つかったリンクを投機的に実行します。
<script type="speculationrules">
{
"prerender": [{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": {"href_matches": "/wp-admin"}},
{ "not": {"href_matches": "/*\\?*(^|&)add-to-cart=*"}},
{ "not": {"selector_matches": ".do-not-prerender"}},
{ "not": {"selector_matches": "[rel~=nofollow]"}}
]
}
}]
}
</script>
熱意
eagerness 設定は、投機を実行するタイミングを示すために使用されます。これは、ドキュメント ルールで特に役立ちます。
conservative: ユーザーがポインタダウンまたはタッチダウンしたときに投機を行います。moderate: パソコンでは、ユーザーがリンクにカーソルを 200 ミリ秒合わせた場合(またはpointerdownイベントがそれより早く発生した場合やhoverイベントのないモバイルで発生した場合)に投機を行います。モバイルでは、2025 年 8 月より、複雑なビューポート ヒューリスティックに基づいてカウントするように変更しました。複雑なビューポート ヒューリスティックは、ユーザーがスクロールを停止してから 500 ミリ秒後にトリガーされます。これは、以前のポインター ダウンからの垂直距離の 30% 以内にあるアンカーを対象とし、アンカーはビューポート内の最大のアンカーの少なくとも 0.5 倍の大きさです。このドキュメントで説明されているとおり。eager: このイーガーネスは、以前はimmediateと同じように動作していましたが、Chrome 143 から変更されました。パソコンでは、リンクにポインタを 10 ミリ秒合わせると投機が実行されます。モバイルでは、2026 年 1 月からシンプルなビューポート ヒューリスティックに基づいて判定するよう変更しました。アンカーがビューポートに入ってから 50 ミリ秒後に、シンプルなビューポート ヒューリスティックがトリガーされます。immediate: できるだけ早く、つまり、投機ルールが検出されたらすぐに投機を行う場合に使用します。
list ルールのデフォルトの eagerness は immediate です。eager、moderate、conservative の各オプションを使用すると、list ルールを、ユーザーが操作する URL の特定のリストに制限できます。ただし、多くの場合、適切な where 条件を持つ document ルールの方が適しています。
document ルールのデフォルトの eagerness は conservative です。ドキュメントは多くの URL で構成される可能性があるため、document ルールで immediate を使用する場合は注意が必要です(次の Chrome の制限セクションもご覧ください)。
どの eagerness 設定を使用するかは、サイトによって異なります。軽量な静的サイトの場合、より積極的に投機することで、コストをほとんどかけずにユーザーにメリットをもたらすことができます。より複雑なアーキテクチャと重いページ ペイロードを持つサイトでは、ユーザーからより積極的な意図のシグナルが得られるまで、投機的な処理の頻度を減らして無駄を制限することをおすすめします。
moderate オプションは中間的なもので、多くのサイトでは、リンクの上にポインタを 200 ミリ秒置いたとき、または pointerdown イベントが発生したときにリンクを事前レンダリングする、次のような投機ルールが有効です。これは、投機ルールの基本的でありながら強力な実装です。
<script type="speculationrules">
{
"prerender": [{
"where": {
"href_matches": "/*"
},
"eagerness": "moderate"
}]
}
</script>
Prefetch
投機ルールは、完全なプリレンダリングを行わずに、ページをプリフェッチするだけの場合にも使用できます。これは、事前レンダリングへの道のりの最初のステップとして適していることがよくあります。
<script type="speculationrules">
{
"prefetch": [{
"urls": ["next.html", "next2.html"]
}]
}
</script>
Prerender until script
Chrome チームは、Speculation Rules API に prerender_until_script を追加する作業も進めています(実装バグをご覧ください)。これはプリフェッチと事前レンダリングの間のステップであり、同様の方法で使用されます。
<script type="speculationrules">
{
"prerender_until_script": [{
"urls": ["next.html", "next2.html"]
}]
}
</script>
NoState prefetch と同様に、HTML ドキュメントと、その HTML で利用可能なサブリソースの両方をプリフェッチします。しかし、それだけではなく、ページの事前レンダリングも開始し、最初のスクリプトが検出された時点で停止します。
つまり、JavaScript がないページや、フッターにのみ JavaScript があるページでは、ページをほぼ完全に事前レンダリングできます。<head> にスクリプトがあるページは、事前レンダリングはできませんが、サブリソースの取得によるメリットは得られます。
これにより、JavaScript の実行による意図しない副作用のリスクを回避しながら、prefetch よりも大幅なパフォーマンスの向上を実現できます。
Chrome の制限
Chrome には、Speculation Rules API の過剰な使用を防ぐための制限が設けられています。
| 熱意 | Prefetch | Prerender(事前レンダリング) |
|---|---|---|
immediate |
50 | 10 |
eager / moderate(モバイル) |
6(FIFO) | 2(FIFO) |
eager / moderate(パソコン) |
2(FIFO) | 2(FIFO) |
conservative |
2(FIFO) | 2(FIFO) |
eager、moderate、conservative の設定は、ユーザー操作に依存し、先入れ先出し(FIFO)方式で動作します。上限に達すると、新しい投機により最も古い投機がキャンセルされ、メモリを節約するために新しい投機に置き換えられます。
キャンセルされた投機は、たとえばそのリンクに再度カーソルを合わせることで、再びトリガーできます。これにより、その URL が再度投機され、最も古い投機が押し出されます。この場合、以前の投機実行によって、その URL の HTTP キャッシュにキャッシュ可能なリソースがキャッシュされているため、さらに投機実行を行うとコストが削減されます。そのため、デフォルトでは上限が 2 という控えめなしきい値に設定されています。モバイルでは「ホバー」がないため、プリフェッチのしきい値を 6 に設定しています。モバイルのビューポート ヒューリスティックは精度が低く、プリフェッチは事前レンダリングよりもコストが低いためです(モバイルの事前レンダリングの制限は 2 に維持しています)。
静的リストルールはユーザーのアクションによってトリガーされないため、上限が高くなります。これは、ブラウザがどのルールが必要で、いつ必要になるかを把握できないためです。
また、Chrome では、モバイルでの eager と moderate の上限を、少なくともプリフェッチについては 5 に引き上げることを検討しています。これは、ヒューリスティックの精度が低いためです。eager を使用しているデベロッパーは、ビューポートで複数のリンクが利用可能な場合に conservative ルールを使用することを検討することをおすすめします。これにより、最初の 2 つのリンクのいずれかとして選択されていない場合でも、投機が実行されます。
immediate の上限も動的であるため、list URL スクリプト要素を削除すると、削除された投機がキャンセルされ、容量が作成されます。
また、Chrome では、次のような特定の状況で投機が使用されないようにします。
- Save-Data。
- 省エネモード: 有効になっていて、バッテリー残量が少ない場合。
- メモリの制約。
- [ページをプリロードする] 設定がオフになっている場合(uBlock Origin などの Chrome 拡張機能によって明示的にオフにされている場合も含む)。
- バックグラウンド タブで開いたページ。
また、Chrome は、有効化されるまで、事前レンダリングされたページにクロスオリジン iframe をレンダリングしません。
これらの条件はすべて、ユーザーに不利益をもたらす過剰な推測の影響を軽減することを目的としています。
ページに投機ルールを含める方法
投機ルールは、ページの HTML に静的に含めることも、JavaScript によってページに動的に挿入することもできます。
- 静的に含まれる投機ルール: たとえば、ニュース メディア サイトやブログでは、多くのユーザーが次にアクセスする可能性が高い最新の記事を事前レンダリングできます。また、
moderateまたはconservativeを含むドキュメント ルールを使用して、ユーザーがリンクを操作する際に投機を行うこともできます。 - 動的に挿入される投機ルール: アプリケーション ロジック、ユーザーに合わせてパーソナライズされたもの、またはその他のヒューリスティックに基づくもの。
リンクにカーソルを合わせたり、リンクをクリックしたりするなどのアクションに基づいて動的挿入を好む場合(過去に多くのライブラリが <link rel=prefetch> で行っていたように)、ドキュメント ルールを確認することをおすすめします。これにより、ブラウザで多くのユースケースを処理できるようになります。
投機ルールは、メインフレームの <head> または <body> に追加できます。サブフレームの投機ルールは実行されません。また、事前レンダリングされたページの投機ルールは、そのページが有効になったときにのみ実行されます。
Speculation-Rules HTTP ヘッダー
投機ルールは、ドキュメントの HTML に直接含めるのではなく、Speculation-Rules HTTP ヘッダーを使用して配信することもできます。これにより、CDN によるデプロイが容易になり、ドキュメントの内容自体を変更する必要がなくなります。
Speculation-Rules HTTP ヘッダーがドキュメントとともに返され、投機ルールを含む JSON ファイルの場所を指します。
Speculation-Rules: "/speculationrules.json"
このリソースは正しい MIME タイプを使用する必要があり、クロスオリジン リソースの場合は CORS チェックに合格する必要があります。
Content-Type: application/speculationrules+json
Access-Control-Allow-Origin: *
相対 URL を使用する場合は、投機ルールに "relative_to": "document" キーを含めることをおすすめします。それ以外の場合、相対 URL は投機ルールの JSON ファイルの URL を基準とした相対 URL になります。これは、同一オリジンのリンクの一部またはすべてを選択する必要がある場合に特に便利です。
投機ルールタグ フィールド
投機ルールの JSON 構文で、ルールセット内のすべての投機ルールに対して全体レベルで「タグ」を追加することもできます。
{
"tag": "my-rules",
"prefetch": [{
"urls": ["next.html"]
}],
"prerender": [{
"urls": ["next2.html"]
}]
}
または、個々のルールレベルで次のようにします。
{
"prefetch": [{
"tag": "my-prefetch-rules",
"urls": ["next.html"]
}],
"prerender": [{
"tag": "my-prerender-rules",
"urls": ["next2.html"]
}]
}
このタグは Sec-Speculation-Tags HTTP ヘッダーに反映され、サーバーで投機ルールをフィルタするために使用できます。次の例に示すように、投機が複数のルールでカバーされている場合、Sec-Speculation-Tags HTTP ヘッダーに複数のタグを含めることができます。
Sec-Speculation-Tags: null
Sec-Speculation-Tags: null, "cdn-prefetch"
Sec-Speculation-Tags: "my-prefetch-rules"
Sec-Speculation-Tags: "my-prefetch-rules", "my-rules", "cdn-prefetch"
一部の CDN は、投機ルールを自動的に挿入しますが、この機能によって配信元サーバーの使用量が増加するのを防ぐため、エッジ キャッシュされていないページに対する投機をブロックします。タグを使用すると、デフォルトのルールセットによって開始された投機を識別できますが、サイトによって追加されたルールはオリジンに渡されます。
ルールセットタグは Chrome DevTools にも表示されます。
推測ルールの target_hint フィールド
投機ルールには target_hint フィールドを含めることもできます。このフィールドには、プリレンダリングされたコンテンツが有効化される場所を示す有効なブラウジング コンテキスト名またはキーワードが含まれます。
<script type=speculationrules>
{
"prerender": [{
"target_hint": "_blank",
"urls": ["next.html"]
}]
}
</script>
このヒントにより、target="_blank" リンクの事前レンダリングの予測を処理できます。
<a target="_blank" href="next.html">Open this link in a new tab</a>
現時点では、Chrome でサポートされているのは "target_hint": "_blank" と "target_hint": "_self"(指定されていない場合のデフォルト)のみで、プリレンダリングのみがサポートされています。プリフェッチはサポートされていません。
target_hint は urls 投機ルールにのみ必要です。ドキュメント ルールの場合、target はリンク自体から認識されます。
投機ルールと SPA
投機ルールは、ブラウザで管理されるフルページ ナビゲーションでのみサポートされ、シングルページ アプリ(SPA)やアプリケーション シェル ページではサポートされません。これらのアーキテクチャでは、ドキュメントのフェッチは使用されず、代わりに API またはデータやページの部分的なフェッチが行われます。これらは、現在のページで処理され、表示されます。いわゆる「ソフト ナビゲーション」に必要なデータは、アプリが投機ルール外でプリフェッチできますが、事前レンダリングはできません。
投機ルールを使用すると、前のページからアプリケーション自体をプリレンダリングできます。これにより、一部の SPA で発生する初期読み込みコストを相殺できます。ただし、アプリ内のルート変更は事前レンダリングできません。
投機ルールをデバッグする
この新しい API の表示とデバッグを支援する Chrome DevTools の新機能については、投機ルールのデバッグに関する専用の投稿をご覧ください。
複数の推測ルール
同じページに複数の投機ルールを追加することもできます。その場合、既存のルールに追加されます。したがって、次のさまざまな方法で one.html と two.html の両方が事前レンダリングされます。
URL のリスト:
<script type="speculationrules">
{
"prerender": [{
"urls": ["one.html", "two.html"]
}]
}
</script>
複数の speculationrules スクリプト:
<script type="speculationrules">
{
"prerender": [{
"urls": ["one.html"]
}]
}
</script>
<script type="speculationrules">
{
"prerender": [{
"urls": ["two.html"]
}]
}
</script>
1 つの speculationrules 内に複数のリストがある
<script type="speculationrules">
{
"prerender": [
{
"urls": ["one.html"]
},
{
"urls": ["two.html"]
}
]
}
</script>
No-Vary-Search サポート
ページをプリフェッチまたは事前レンダリングする場合、特定の URL パラメータ(技術的には検索パラメータと呼ばれる)は、サーバーから実際に配信されるページにとって重要ではなく、クライアントサイドの JavaScript でのみ使用されることがあります。
たとえば、UTM パラメータは Google アナリティクスでキャンペーン測定に使用されますが、通常、サーバーから配信されるページが異なることはありません。つまり、page1.html?utm_content=123 と page1.html?utm_content=456 はサーバーから同じページを配信するため、同じページをキャッシュから再利用できます。
同様に、アプリケーションは、クライアント側でのみ処理される他の URL パラメータを使用する場合があります。
No-Vary-Search の提案では、サーバーは、配信されるリソースに違いをもたらさないパラメータを指定できます。これにより、ブラウザは、これらのパラメータのみが異なるドキュメントの以前にキャッシュに保存されたバージョンを再利用できます。これは、Chrome(および Chromium ベースのブラウザ)で、プリフェッチと事前レンダリングの両方のナビゲーション予測でサポートされています。
投機ルールでは、expects_no_vary_search を使用して、No-Vary-Search HTTP ヘッダーが返されることが想定される場所を示すことができます。これにより、レスポンスが表示される前に不要なダウンロードが行われるのを防ぐことができます。
<script type="speculationrules">
{
"prefetch": [{
"urls": ["/products"],
"expects_no_vary_search": "params=(\"id\")"
}]
}
</script>
<a href="/products?id=123">Product 123</a>
<a href="/products?id=124">Product 124</a>
この例では、/products の最初のページの HTML は、商品 ID 123 と 124 の両方で同じです。ただし、ページの内容は最終的に、JavaScript を使用して id 検索パラメータで商品データを取得するクライアントサイド レンダリングに基づいて異なります。そのため、その URL を積極的にプリフェッチします。この URL は、ページが任意の id 検索パラメータに使用できることを示す No-Vary-Search HTTP ヘッダーを返す必要があります。
ただし、プリフェッチが完了する前にユーザーがリンクをクリックすると、ブラウザが /products ページを受信していない可能性があります。この場合、ブラウザは No-Vary-Search HTTP ヘッダーが含まれるかどうかを認識しません。この場合、ブラウザは、リンクを再度取得するか、プリフェッチが完了するまで待機して No-Vary-Search HTTP ヘッダーが含まれているかどうかを確認するかを選択することになります。expects_no_vary_search 設定により、ブラウザはページ レスポンスに No-Vary-Search HTTP ヘッダーが含まれることを認識し、プリフェッチが完了するまで待機できます。
expects_no_vary_search に複数のパラメータを追加することもできます。その場合は、スペースで区切ります(No-Vary-Search は HTTP 構造化ヘッダーであるため)。
"expects_no_vary_search": "params=(\"param1\" \"param2\" \"param3\")"
投機ルールに関する制限と今後の機能強化
投機ルールは同じタブ内で開かれたページに限定されますが、この制限を緩和する取り組みが進められています。
デフォルトでは、事前レンダリングは同一オリジンのページに制限されています。同一サイトのクロスオリジン ページの事前レンダリング(たとえば、https://a.example.com が https://b.example.com のページを事前レンダリングする)を有効にできます。これを使用するには、推測されたページ(この例では https://b.example.com)が Supports-Loading-Mode: credentialed-prerender HTTP ヘッダーを含めることでオプトインする必要があります。そうしないと、Chrome は推測をキャンセルします。
将来のバージョンでは、事前レンダリングされたページに Cookie が存在せず、事前レンダリングされたページが同様の Supports-Loading-Mode: uncredentialed-prerender HTTP ヘッダーでオプトインしている限り、同一サイト以外のクロスオリジン ページの事前レンダリングも許可される可能性があります。
投機ルールはすでにクロスオリジンのプリフェッチをサポートしています。同一サイトのクロスオリジンのプリフェッチには制限がありません。異なるサイトのクロスオリジン プリフェッチは、クロスオリジン ドメインの Cookie が存在しない場合にのみサポートされます。ユーザーが以前にそのサイトにアクセスした際の Cookie が存在する場合、投機は使用されず、DevTools に失敗が表示されます。
現在の制限を考慮すると、内部リンクと外部リンクの両方でユーザー エクスペリエンスを向上させるパターンとして、同一オリジンの URL を事前レンダリングし、クロスオリジンの URL をプリフェッチする方法があります。
<script type="speculationrules">
{
"prerender": [{
"where": { "href_matches": "/*" },
"eagerness": "moderate"
}],
"prefetch": [{
"where": { "not": { "href_matches": "/*" } },
"eagerness": "moderate"
}]
}
</script>
クロスオリジン リンクのクロスオリジン投機をデフォルトで防止する制限は、セキュリティ上必要です。これは、クロスオリジンの宛先に対する <link rel="prefetch"> の改善です。 では、Cookie は送信されませんが、プリフェッチは試行されます。その結果、プリフェッチが無駄になり、再送信が必要になるか、さらに悪いことに、誤ったページ読み込みが発生することになります。
Speculation Rules API のサポートを検出する
Speculation Rules API のサポートは、標準の HTML チェックで検出できます。
if (HTMLScriptElement.supports && HTMLScriptElement.supports('speculationrules')) {
console.log('Your browser supports the Speculation Rules API.');
}
JavaScript を使用して投機ルールを動的に追加する
JavaScript を使用して prerender 投機ルールを追加する例を次に示します。
if (HTMLScriptElement.supports &&
HTMLScriptElement.supports('speculationrules')) {
const specScript = document.createElement('script');
specScript.type = 'speculationrules';
specRules = {
prerender: [
{
urls: ['/next.html'],
},
],
};
specScript.textContent = JSON.stringify(specRules);
console.log('added speculation rules to: next.html');
document.body.append(specScript);
}
JavaScript 挿入を使用した Speculation Rules API 事前レンダリングのデモは、こちらの事前レンダリング デモページでご覧いただけます。
innerHTML を使用して <script type = "speculationrules"> 要素を DOM に直接挿入しても、セキュリティ上の理由により投機ルールは登録されません。前述のように追加する必要があります。ただし、新しいリンクを含む innerHTML を使用して動的に挿入されたコンテンツは、ページ上の既存のルールによって取得されます。
同様に、Chrome DevTools の [Elements] パネルを直接編集して <script type = "speculationrules"> 要素を追加しても、投機ルールは登録されません。代わりに、この要素を DOM に動的に追加するスクリプトをコンソールから実行して、ルールを挿入する必要があります。
タグ マネージャーを使用して投機ルールを追加する
Google タグ マネージャー(GTM)などのタグ マネージャーを使用して投機ルールを追加するには、前述と同じ理由で、GTM を介して <script type = "speculationrules"> 要素を直接追加するのではなく、JavaScript を介して挿入する必要があります。
なお、GTM は const をサポートしていないため、この例では var を使用しています。
推測ルールをキャンセルする
予測ルールを削除すると、事前レンダリングがキャンセルされます。ただし、この時点では、プリレンダリングを開始するためにリソースがすでに消費されている可能性が高いため、プリレンダリングをキャンセルする必要がある場合は、プリレンダリングを行わないことをおすすめします。一方、キャッシュに保存されたリソースは引き続き再利用できるため、キャンセルが完全に無駄になることはなく、将来の投機とナビゲーションに役立つ可能性があります。
Clear-Site-Data HTTP ヘッダーと prefetchCache ディレクティブおよび prerenderCache ディレクティブを使用して、投機的実行をキャンセルすることもできます。
これは、サーバーで状態が変更された場合に役立ちます。たとえば、「カートに追加」API、ログイン API、ログアウト API を呼び出す場合です。
理想的には、これらの状態の更新は Broadcast Channel API などの API を使用して、事前レンダリングされたページに伝播されます。ただし、これが不可能な場合や、そのようなロジックが実装されるまでは、投機をキャンセルする方が簡単です。
投機ルールとコンテンツ セキュリティ ポリシー
投機ルールは <script> 要素を使用するため、JSON のみを含む場合でも、サイトで script-src Content-Security-Policy を使用している場合は、ハッシュまたはノンスを使用して、このポリシーに含める必要があります。
新しい inline-speculation-rules を script-src に追加して、ハッシュまたはノンス スクリプトから挿入された <script type="speculationrules"> 要素をサポートできるようになりました。これは、最初の HTML に含まれるルールをサポートしていないため、厳格な CSP を使用するサイトでは、JavaScript によってルールを挿入する必要があります。
事前レンダリングを検出して無効にする
通常、事前レンダリングは、ページのレンダリングを高速化(多くの場合、瞬時にレンダリング)できるため、ユーザーにとって有益な機能です。プリレンダリングされたページは、他の方法では実現が難しい優れたユーザー エクスペリエンスを提供できるため、ユーザーとサイト所有者の両方にメリットがあります。
ただし、ページの事前レンダリングを行いたくない場合もあります。たとえば、最初のリクエストに基づいて、またはページで実行される JavaScript に基づいて、ページの状態が変化する場合などです。
Chrome でプリレンダリングを有効または無効にする
事前レンダリングは、chrome://settings/performance/ で [ページをプリロードする] 設定が有効になっている Chrome ユーザーに対してのみ有効になります。また、メモリの少ないデバイスや、オペレーティング システムがデータセーバー モードまたは省エネモードになっている場合も、事前レンダリングは無効になります。Chrome の制限事項のセクションをご覧ください。
サーバーサイドで事前レンダリングを検出して無効にする
事前レンダリングされたページは、Sec-Purpose HTTP ヘッダーとともに送信されます。
Sec-Purpose: prefetch;prerender
Speculation Rules API を使用してプリフェッチされたページでは、このヘッダーが prefetch に設定されます。
Sec-Purpose: prefetch
サーバーは、このヘッダーに基づいて応答し、投機的リクエストをログに記録したり、異なるコンテンツを返したり、事前レンダリングを防止したりできます。成功以外の最終レスポンス コード(リダイレクト後の 200 ~ 299 の範囲外)が返された場合、ページは事前レンダリングされず、プリフェッチ ページは破棄されます。また、204 と 205 のレスポンスは、事前レンダリングでは無効ですが、プリフェッチでは有効です。
特定のページを事前レンダリングしたくない場合は、2XX 以外のレスポンス コード(503 など)を返すのが、事前レンダリングを確実に回避する最善の方法です。ただし、最適なエクスペリエンスを提供するには、事前レンダリングを許可し、ページが実際に表示されたときにのみ実行する必要があるアクションを JavaScript を使用して遅らせることをおすすめします。
JavaScript でプリレンダリングを検出する
document.prerendering API は、ページの事前レンダリング中に true を返します。これを使用すると、ページが実際に有効化されるまで、事前レンダリング中の特定のアクティビティを防止または遅延できます。
事前レンダリングされたドキュメントが有効になると、PerformanceNavigationTiming の activationStart も、事前レンダリングが開始されてからドキュメントが実際に有効になるまでの時間を表すゼロ以外の時間に設定されます。
次のように、事前レンダリングと事前レンダリングされたページを確認する関数を使用できます。
function pagePrerendered() {
return (
document.prerendering ||
self.performance?.getEntriesByType?.('navigation')[0]?.activationStart > 0
);
}
ページが(全体または部分的に)事前レンダリングされたかどうかを確認する最も簡単な方法は、ページが有効化された後に DevTools を開き、コンソールに「performance.getEntriesByType('navigation')[0].activationStart」と入力することです。ゼロ以外の値が返された場合、ページが事前レンダリングされたことがわかります。
ユーザーがページを表示してページが有効になると、prerenderingchange イベントが document にディスパッチされます。これを使用して、以前はページの読み込み時にデフォルトで開始されていたアクティビティを有効にできます。ただし、ユーザーが実際にページを表示するまで、アクティビティを遅らせる必要があります。
これらの API を使用すると、フロントエンドの JavaScript で事前レンダリングされたページを適切に検出して処理できます。
アナリティクスへの影響
分析は、ウェブサイトの使用状況を測定するために使用されます。たとえば、Google アナリティクスを使用してページビューやイベントを測定します。または、Real User Monitoring(RUM)を使用してページのパフォーマンス指標を測定します。
ページは、ユーザーがページを読み込む可能性が高い場合にのみ、事前レンダリングする必要があります。そのため、Chrome のアドレスバーの事前レンダリング オプションは、そのような高い確率(80% 以上)の場合にのみ実行されます。
ただし、特に Speculation Rules API を使用する場合、事前レンダリングされたページがアナリティクスに影響を与える可能性があります。サイト所有者は、事前レンダリングされたページのアナリティクスを有効にするために、追加のコードを追加する必要がある場合があります。これは、すべてのアナリティクス プロバイダがデフォルトでこれを行うわけではないためです。
これは、ドキュメントが事前レンダリング中の場合は prerenderingchange イベントを待機し、現在の場合はすぐに解決する Promise を使用することで実現できます。
// Set up a promise for when the page is activated,
// which is needed for prerendered pages.
const whenActivated = new Promise((resolve) => {
if (document.prerendering) {
document.addEventListener('prerenderingchange', resolve, {once: true});
} else {
resolve();
}
});
async function initAnalytics() {
await whenActivated;
// Initialise your analytics
}
initAnalytics();
別の方法として、ページが最初に表示されるまで分析アクティビティを遅らせることもできます。これにより、事前レンダリングの場合と、タブがバックグラウンドで開かれた場合(右クリックして新しいタブで開くなど)の両方に対応できます。
// Set up a promise for when the page is first made visible
const whenFirstVisible = new Promise((resolve) => {
if (document.hidden) {
document.addEventListener('visibilitychange', resolve, {once: true});
} else {
resolve();
}
});
async function initAnalytics() {
await whenFirstVisible;
// Initialise your analytics
}
initAnalytics();
これは、分析などのユースケースでは理にかなっていますが、他のユースケースでは、より多くのコンテンツを読み込む必要があるため、document.prerendering と prerenderingchange を使用して、プリレンダリング ページを具体的にターゲットに設定することが必要になる場合があります。
プリレンダリング中に他のコンテンツを保留する
前述の API を使用して、事前レンダリング フェーズ中に他のコンテンツを保留することもできます。これには、JavaScript の特定の部分や、プリレンダリング段階で実行したくないスクリプト要素全体を指定できます。
たとえば、次のスクリプトがあるとします。
<script src="https://example.com/app/script.js" async></script>
これを、前の whenActivated 関数に基づいてのみ挿入される、動的に挿入されるスクリプト要素に変更できます。
async function addScript(scriptUrl) {
await whenActivated;
const script = document.createElement('script');
script.src = 'scriptUrl';
document.body.appendChild(script);
}
addScript('https://example.com/app/script.js');
これは、分析を含む個別のスクリプトを保留したり、訪問中に変化する可能性のある状態やその他の変数に基づいてコンテンツをレンダリングしたりする場合に便利です。たとえば、おすすめ、ログイン状態、ショッピング カートのアイコンなどは、最新の情報が表示されるように、すべて保留されることがあります。
これは、プリレンダリングを使用すると発生する可能性が高くなりますが、前述のバックグラウンド タブで読み込まれたページにも当てはまります(そのため、whenActivated の代わりに whenFirstVisible 関数を使用できます)。
多くの場合、状態は一般的な visibilitychange の変更時にも確認するのが理想的です。たとえば、バックグラウンドに移動したページに戻ったときに、ショッピング カートのカウンタをカート内の最新のアイテム数に更新する必要があります。これは、事前レンダリングに固有の問題ではなく、事前レンダリングによって既存の問題がより顕著になっただけです。
Chrome がスクリプトや関数を手動でラップする必要性を軽減する方法の一つは、前述のように特定の API を保留することです。また、サードパーティの iframe はレンダリングされないため、手動で保留する必要があるのは、この上に表示されるコンテンツのみです。
パフォーマンスの測定
パフォーマンス指標を測定する場合、ブラウザ API が報告するページの読み込み時間ではなく、有効化時間に基づいて測定する方がよいかどうかを検討する必要があります。
Core Web Vitals は、Chrome ユーザー エクスペリエンス レポートを通じて Chrome で測定されるもので、ユーザー エクスペリエンスを測定することを目的としています。これらは有効化時間に基づいて測定されます。これにより、たとえば LCP が 0 秒になることがよくあります。これは、Core Web Vitals を改善する優れた方法であることを示しています。
バージョン 3.1.0 以降、web-vitals ライブラリが更新され、Chrome が Core Web Vitals を測定するのと同じ方法で、事前レンダリングされたナビゲーションを処理するようになりました。このバージョンでは、ページが完全にまたは部分的に事前レンダリングされた場合、Metric.navigationType 属性の指標に事前レンダリングされたナビゲーションのフラグも設定されます。
プリレンダリングを測定する
ページが事前レンダリングされているかどうかは、PerformanceNavigationTiming のゼロ以外の activationStart エントリで確認できます。これは、ページビューをロギングするときに、カスタム ディメンションなどを使用してロギングできます。たとえば、前述の pagePrerendered 関数を使用します。
// Set Custom Dimension for Prerender status
gtag('set', { 'dimension1': pagePrerendered() });
// Initialise GA - including sending page view by default
gtag('config', 'G-12345678-1');
これにより、他のタイプのナビゲーションと比較して、プリレンダリングされたナビゲーションの数をアナリティクスに表示できます。また、パフォーマンス指標やビジネス指標をこれらの異なるナビゲーション タイプに関連付けることもできます。ページの読み込みが速いほどユーザーの満足度が高くなり、事例紹介で示されているように、ビジネス指標に大きな影響を与えることがよくあります。
インスタント ナビゲーションのためにページを事前レンダリングすることのビジネスへの影響を測定することで、このテクノロジーを使用してより多くのナビゲーションを事前レンダリングできるようにするために、より多くの労力を投資する価値があるかどうか、またはページが事前レンダリングされない理由を調査する価値があるかどうかを判断できます。
ヒット率を測定する
プリレンダリング後にアクセスされたページの影響を測定するだけでなく、プリレンダリングされたものの、その後アクセスされなかったページを測定することも重要です。これは、事前レンダリングが多すぎて、ユーザーの貴重なリソースをほとんどメリットなく消費していることを示している可能性があります。
これは、HTMLScriptElement.supports('speculationrules') を使用してブラウザが事前レンダリングをサポートしていることを確認した後、投機ルールが挿入されたときにアナリティクス イベントを発生させて、事前レンダリングがリクエストされたことを示すことで測定できます。(事前レンダリングがリクエストされたからといって、事前レンダリングが開始または完了したとは限りません。前述のように、事前レンダリングはブラウザへのヒントであり、ユーザー設定、現在のメモリ使用量、その他のヒューリスティックに基づいて、ページを事前レンダリングしないことを選択する場合があります)。
その後、これらのイベントの数を実際のプリレンダリング ページビューと比較できます。または、有効化時に別のイベントを発生させると、比較しやすくなります。
「ヒット成功率」は、これら 2 つの数値の差から概算できます。Speculation Rules API を使用してページを事前レンダリングしているページでは、ルールを適切に調整して、高いヒット率を維持し、ユーザーのリソースを有効に活用することと、無駄に使用することのバランスを保つことができます。
なお、一部のプリレンダリングは、投機ルールだけでなく、アドレスバーのプリレンダリングによって行われている可能性があります。これらを区別する場合は、document.referrer を確認します(アドレスバー ナビゲーション(事前レンダリングされたアドレスバー ナビゲーションを含む)の場合は空白になります)。
プリレンダリングが行われていないページも確認してください。これは、アドレスバーからでもプリレンダリングの対象外であることを示している可能性があります。この場合、このパフォーマンス強化のメリットを享受できていない可能性があります。Chrome チームは、bfcache テストツールと同様に、事前レンダリングの適格性をテストするための追加ツールを追加することを検討しています。また、事前レンダリングが失敗した理由を公開する API を追加する可能性もあります。
拡張機能への影響
拡張機能の作成者がプリレンダリングされたページについて考慮する必要がある追加事項については、Chrome 拡張機能: インスタント ナビゲーションをサポートするための API の拡張に関する専用の投稿をご覧ください。
フィードバック
事前レンダリングは Chrome チームによって積極的に開発されており、Chrome 108 リリースで利用可能になった機能の範囲を拡大する計画が多数あります。GitHub リポジトリまたは Issue Tracker を使用したフィードバックをお待ちしております。このエキサイティングな新しい API のケーススタディをぜひお寄せください。
関連リンク
- 投機ルールの Codelab
- 投機ルールのデバッグ
- NoState プリフェッチの概要
- Speculation Rules API の仕様
- ナビゲーションの推測の GitHub リポジトリ
- Chrome 拡張機能: インスタント ナビゲーションをサポートする API の拡張
謝辞
サムネイル画像: Marc-Olivier Jodoin、Unsplash より