複雑なサイトに推測ルールを実装するガイド

公開日: 2025 年 3 月 7 日

Speculation Rules API を使用すると、今後のページ ナビゲーションをプリフェッチまたはプリレンダリングして、ページ ナビゲーションを高速化(または即時化)し、パフォーマンスを向上させることができます。

この API は、実装の容易さを念頭に置いて設計されていますが、複雑なサイトでは、使用前に考慮すべき点がいくつかあります。このガイドでは、サイト所有者がこれらの考慮事項を理解できるようにします。

計画

3 つの段階(計画、実装、測定)のうち、計画がハイライト表示されている。

推測ルールを実装する前に、API の実装方法(いくつかの選択肢があります)と推測の費用(推測するページを判断する際に役立ちます)を検討することをおすすめします。

推測ルールの実装方法を決定する

最初に決定すべきことの 1 つは、サイトに推測ルールを実装する方法です。実装方法はいくつかあります。

  • ページの HTML に直接
  • JavaScript を使用する
  • HTTP ヘッダーを使用する

最終的には、どの方法でも同じ効果が得られます。ただし、実装の容易性や柔軟性という点でメリットがあります。

サイトは、最も適したオプションを選択する必要があります。必要に応じて、これらのオプションを組み合わせて使用することもできます。また、プラグイン(WordPress の Speculative Loading プラグインなど)やライブラリ、プラットフォームを使用して実装することもできます。これらのオプションは自動的に選択される場合もありますが、利用可能なオプションを把握しておくことは重要です。

ページの HTML に推測ルールを直接含める

推測ルールは、HTML に <script type="speculationrules"> 要素を含めることで、ページに直接実装できます。これは、テンプレートを使用して静的サイトのビルド時に追加することも、ページがリクエストされたときにサーバーが実行時に追加することもできます。エッジワーカーによって HTML に挿入することもできます(ただし、このガイドで後述する HTTP ヘッダー メソッドの方が簡単です)。

これにより、サイト全体に静的ルールを含めることができますが、ドキュメント ルールは動的のままにできます。CSS クラスによってトリガーされるルールを使用して、ページからレンダリングする URL を選択できます。

<script type="speculationrules">
  {
    "prerender": [{
      "where": { "selector_matches": ".prerender" }
    }],
    "prefetch": [{
      "where": { "selector_matches": ".prefetch" }
    }]
  }
</script>

上記のスクリプトでは、prerender クラスのリンクがプリレンダリングされ、同様に、リンクに prefetch クラスが付いている場合はプリフェッチされます。これにより、デベロッパーはこれらのクラスを HTML に含めて推測をトリガーできます。

ページの初期 HTML にこれらのクラスのリンクが含まれるだけでなく、これらのクラスがアプリによって動的に追加された場合、リンクも推測されます。これにより、アプリは必要に応じて推測をトリガー(および削除)できます。これは、より具体的な推測ルールを作成または削除するよりも簡単な場合があります。サイトのほとんどで使用するベースルールとページ固有のルールを設定したい場合は、ページごとに複数の推測ルールを含めることもできます。

より具体的な推測ルールを使用する必要がある場合は、ページ固有またはテンプレート固有のルールを使用して、特定のページまたはページタイプに異なるルールを適用できます。

最後に、サーバーサイドでレンダリングされるページには、そのページのアナリティクス情報や特定のページでの一般的なユーザー ジャーニーなど、サーバーで利用可能な情報に基づいて、より動的ルールを設定することもできます。

JavaScript を使用して投機ルールを追加する

ルールをオンページ スクリプトに含める代わりに、JavaScript を使用して挿入することもできます。これにより、ページ テンプレートの更新頻度を減らすことができます。たとえば、タグ マネージャーでルールを挿入すると、推測ルールをすばやくロールアウトできます(必要に応じてすばやく無効にすることもできます)。

また、ユーザーがページを操作した方法に基づいて、動的クライアントサイド ルールを適用することもできます。たとえば、ユーザーがカートに商品を追加した場合は、購入手続きページをプリレンダリングできます。また、特定の条件に基づいて推測をトリガーすることもできます。API には、基本的なインタラクション ベースのルールを可能にする早期取得設定が含まれていますが、JavaScript では、デベロッパーが独自のロジックを使用して、推測を行うタイミングとページを決定できます。

前述のように、新しいルールを挿入する別の方法として、ページにベース ドキュメント ルールを設定し、リンクに適切なクラスを追加してルールに一致するようにし、JavaScript でドキュメント ルールをトリガーする方法があります。

HTTP ヘッダーを使用して投機ルールを追加する

デベロッパーが選択できる最後のオプションは、HTTP ヘッダーを使用してルールを含めることです。

Speculation-Rules: "/speculationrules.json"

ルール リソース(この例では /speculationrules.json)の配信と使用方法には追加の要件があります。

このオプションを使用すると、ドキュメントのコンテンツを変更しなくても、CDN によるデプロイが容易になります。つまり、JavaScript を使用して推測ルールを動的に変更することはできません。ただし、CSS セレクタ トリガーを使用するドキュメント ルールでは、リンクから prerender クラスを削除するなど、動的な変更を許可できます。

JavaScript オプションと同様に、HTTP ヘッダーを使用して推測ルールを実装すると、サイトのコンテンツとは別に実装できるため、サイト全体を再ビルドしなくてもルールを簡単に追加、削除できます。

費用への影響を考慮する

推測ルールを実装する前に、この API を使用するとユーザーとサイトの両方にどのような費用が発生するかを検討することをおすすめします。費用には、帯域幅(ユーザーとサイトの両方に費用が発生)と処理費用(クライアント側とサーバー側の両方)が含まれます。

ユーザーの費用を考慮する

推測読み込みとは、ユーザーが新しいページに移動する可能性のある場所を推測することを意味します。ただし、そのナビゲーションが実行されなかった場合、リソースが浪費される可能性があります。そのため、特に以下のユーザーへの影響を意識する必要があります。

  • 将来のナビゲーションのダウンロードに使用される追加の帯域幅(特に、帯域幅が制限される可能性のあるモバイル デバイスの場合)。
  • プリレンダリングを使用する際、それらのページをレンダリングするための追加の処理コスト。

予測が完全に正確であれば、追加費用は発生しません。ユーザーはいずれにしてもそれらのページにアクセスするためです。唯一の違いは、費用が前倒しされることです。ただし、将来を完全に正確に予測することは不可能であり、投機戦略が積極的であればあるほど、無駄になるリスクが高くなります。

Chrome ではこの問題を慎重に検討し、API に多くの機能を組み込んでいます。そのため、費用は想像よりもはるかに低くなります。特に、HTTP キャッシュを再利用し、クロスオリジン iframe を読み込まないことで、同じサイト内のナビゲーションをプリレンダリングするコストは、キャッシュに保存されていないリソースを含むフルページよりも大幅に小さくなることが多く、推測読み込みのコストは想定よりも低くなります。

ただし、これらの安全対策を講じていても、サイトはどのページを推測するか、およびそのような推測によるユーザーの費用を慎重に検討する必要があります。推測読み込みの適切な候補としては、(アナリティクスや一般的なユーザー ジャーニーに基づいて)高い信頼度で合理的に予測できるものや、費用が低いもの(リッチでないページなど)が挙げられます。

有効になるまで遅らせる JavaScript についても検討してください。必要になるまでコンテンツを遅延読み込みする場合と同様に、この方法ではプリレンダリングの費用を抑えながら、ユーザー エクスペリエンスを大幅に改善できます。低価格の投機では、より頻繁に、または積極的に投機を行うことができます。

これが不可能な場合は、中程度または保守的なエアグリス ルールを使用する、より攻撃性の低い戦略をおすすめします。または、信頼度が低い場合はプリフェッチを使用します。プリフェッチは、信頼度が低い場合のプリレンダリングよりもコストが大幅に低く、リンクにカーソルを合わせたり実際にクリックしたりするなど、信頼度が高まった場合は完全なプリレンダリングにアップグレードできます。

バックエンドの追加負荷を考慮する

サイト所有者は、ユーザーに発生する追加費用だけでなく、独自のインフラストラクチャ費用も考慮する必要があります。すべてのページで 2 回、3 回、またはそれ以上のページ読み込みが発生する場合、この API を使用するとバックエンドの費用が増加する可能性があります。

ページとリソースをキャッシュに保存できるようにすると、送信元の負荷が大幅に軽減され、全体的なリスクも軽減されます。CDN と組み合わせると、配信元サーバーの負荷は最小限に抑えられます。ただし、CDN の費用増加を考慮してください。

サーバーまたは CDN を使用して、sec-purpose HTTP ヘッダーで識別された推測結果を制御することもできます。たとえば、Cloudflare の Speed Brain プロダクトは、CDN のエッジサーバーですでにキャッシュに保存されている推測のみを許可し、オリジンにリクエストを送信しません。

ただし、通常、推測読み込みは同じオリジンのページ読み込みに使用されるため、ユーザーはブラウザのキャッシュに共有リソースをすでに保存しています(そもそもキャッシュに保存可能であることを前提としています)。そのため、通常、推測はページ全体の読み込みほどコストがかかりません。

推測しすぎず、推測しなさすぎないバランスを保つ

Speculation Rules API を最大限に活用するには、過剰な推測(費用が不必要に支払われ、推測が使用されない)と過度に保守的な推測(推測が不十分であるか、遅すぎてほとんどメリットが得られない)のバランスを見つけることが重要です。

費用が低い場合(CDN エッジノードにキャッシュに保存されている静的に生成された小さなページなど)、推測をより積極的に行うことができます。

ただし、CDN エッジでキャッシュに保存できない可能性のある、より大規模でリッチなページの場合は、より慎重に行う必要があります。同様に、リソースを大量に消費するページは、ネットワーク帯域幅や処理能力を使い果たして、現在のページに悪影響を及ぼす可能性があります。API の目的はパフォーマンスの向上であるため、パフォーマンスの低下は望ましくありません。これは、プリレンダリングを 1 ~ 2 ページに抑える理由の 1 つです(また、Chrome では、イージングの設定に応じて、一度に 2 ~ 10 件のプリレンダリングに制限されています)。

推測ルールを実装する手順

3 つのステージ(計画、実装、測定)のうち、実装がハイライト表示されている。

推測ルールの実装方法を決定したら、次に、推測する内容とそのロールアウト方法を計画する必要があります。静的な個人ブログなどのシンプルなサイトでは、特定のページの完全なプリレンダリングにすぐにジャンプできますが、複雑なサイトでは、考慮すべき複雑さがさらにあります。

プリフェッチから始める

通常、プリフェッチはほとんどのサイトで比較的安全に実装できます。これは、CloudflareWordPress などの大規模なロールアウトを含む、多くのサイトで最初に採用されるアプローチです。

注意すべき主な問題は、URL のプリフェッチによって状態の変化やサーバーサイドの費用が発生することです(特にキャッシュに保存できないページの場合)。/logout ページのプリフェッチなど、状態の変更は GET リンクとして実装しないのが理想的ですが、残念ながらウェブでは珍しくありません。

このような URL は、ルールから明示的に除外できます。

<script type="speculationrules">
  {
    "prefetch": [{
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": {"href_matches": "/logout"}}
        ]
      },
      "eagerness": "moderate"
    }]
  }
</script>

プリフェッチは、moderate または conservativeeagerness 設定を使用して、1 つのページから別のページへの一般的なナビゲーションに限定することも、ホバーまたはクリック時に同じオリジンのすべてのリンクに適用することもできます。conservative 設定はリスクが最も低いですが、見込まれるリターンも最も低くなります。moderate から始める場合は、少なくとも moderate に進むようにしてください。パフォーマンスをさらに向上させるには、eager まで進むことをおすすめします(必要に応じて prerender にアップグレードしてください)。

低リスクのプリレンダリング

プリフェッチ推測はデプロイが簡単ですが、API のパフォーマンスを最大限に高めるのはプリレンダリングです。推測の直後にページがアクセスされない場合は、追加の考慮事項が生じる可能性があります(これについては次のセクションで説明します)。ただし、moderate または conservative の事前レンダリングでは、直後にナビゲーションが発生する可能性が高いため、比較的リスクの低い次のステップになる可能性があります。

<script type="speculationrules">
  {
    "prerender": [{
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": {"href_matches": "/logout"}}
        ]
      },
      "eagerness": "moderate"
    }]
  }
</script>

一般的なページをプリフェッチして、非エアガード プリレンダリングを改善

一般的な方法の 1 つは、eager 設定で読み込み時に頻繁にアクセスされる次のページを少数プリフェッチし(URL リストで指定するか、selector_matches を使用する)、moderate 設定でプリレンダリングすることです。リンクにカーソルを合わせる頃には HTML プリフェッチが完了している可能性が高いため、プリフェッチなしでカーソルを合わせた時点でプリレンダリングするよりも効果的です。

<script type="speculationrules">
  {
    "prefetch": [{
      "urls": ["next.html", "next2.html"],
      "eagerness": "eager"
    }],
    "prerender": [{
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": {"href_matches": "/logout"}}
        ]
      },
      "eagerness": "moderate"
    }]
  }
</script>

以前のプリレンダリング

moderate ドキュメント ルールでは、API の使用リスクが比較的低く、実装も簡単ですが、完全なプリレンダリングを行うには時間が足りないことがよくあります。この API で可能になる即時ナビゲーションを実現するには、それ以上の対応が必要で、ページをより積極的にプリレンダリングする必要があります。

これは、URL の静的リスト(前述のプリフェッチの例など)を使用するか、selector_matches で少数の URL(理想的には 1 ~ 2 ページ)を識別し、他の URL をドキュメント ルールでカバーすることで実現できます。

<script type="speculationrules">
  {
    "prerender": [
      {
        "where": {
          "selector_matches": : ".prerender"
        },
        "eagerness": "eager",
      },
      {
        "where": {
          "and": [
            { "href_matches": "/*" },
            { "not": {"href_matches": "/logout"}}
          ]
        },
        "eagerness": "moderate"
      }
    ]
  }
</script>

次回のナビゲーションを正確に予測するには、トラフィック分析が必要になる場合があります。サイトでの一般的なユーザー ジャーニーを把握することも、推測読み込みの適切な候補を特定するうえで役立ちます。

より積極的なプリレンダリングに移行すると、アナリティクス、広告、JavaScript に関する考慮事項が増える可能性があります。また、プリレンダリングされたページを最新の状態に保つ必要性や、状態の変化に関する推測をキャンセルまたは更新する必要性も生じる可能性があります。

アナリティクス、広告、JavaScript

プリレンダリングを使用する場合は、複雑なサイトではアナリティクスへの影響も考慮する必要があります。通常、ページが推測されたときにページ(または広告)ビューを記録するのではなく、推測が有効になっている場合にのみ記録します。

一部の分析プロバイダ(Google アナリティクスなど)と広告プロバイダ(Google パブリッシャー タグなど)は、推測ルールをすでにサポートしており、ページが有効になるまでビューを記録しません。ただし、実装している他のプロバイダやカスタム アナリティクスについては、追加の検討が必要になる場合があります。

JavaScript にチェックを追加して、ページが有効化または表示されるまで特定のコードが実行されないようにしたり、<script> 要素全体をそのようなチェックでラップしたりすることもできます。ページでタグ マネージャーを使用してこのようなスクリプトを挿入している場合は、タグ マネージャー スクリプト自体を遅らせることで、これらをすべて一度に解決できる可能性があります。

同様に、同意管理プラットフォームを使用すると、サードパーティ スクリプトを有効になるまで遅らせることができます。Google は、さまざまな同意管理プラットフォームと連携して、プリレンダリングに対応するよう取り組んできました。Google は、同様の取り組みを検討している他の企業をサポートいたします。PubTech は、プリレンダリング中に JavaScript を実行するかブロックするかをデベロッパーが選択できるようにするサービスを提供しています。

アプリケーション コードの場合も、同様に変更を追加して、アクティベーションまでコードの実行を遅らせることができます。特に、ページのレンダリングに JavaScript コードが不要な場合は、この方法が有効です。これはより迅速で安全な方法ですが、有効化時にすべてのコードが一度に実行されます。これにより、ページが完全に読み込まれ、操作できる状態に見えるため、特にINP に影響する可能性があるアクティベーション時に多くの作業が発生する可能性があります。

また、JavaScript に依存するコンテンツ(クライアントサイド レンダリング コンテンツなど)がある場合、この処理を遅らせると、プリレンダリングがもたらす LCPCLS へのプラスの効果が低下します。プリレンダリング フェーズ中に実行する JavaScript の量を増やす、よりターゲットを絞ったアプローチでは、エクスペリエンスが向上しますが、実装が簡単とは言えません。

複雑なサイトの場合は、最初は多くのスクリプトタグを完全に遅らせることをおすすめします。ただし、API を最大限に活用するには、プリレンダリング中にできるだけ多くの JavaScript を実行できるようにすることが最終的な目標となります。

アナリティクスや広告に関する懸念があるサイトでは、プリレンダリングをサポートするために必要なことを検討しながら、プリフェッチから始めることもできます。

プリレンダリングの推測を更新

ページをナビゲーションの前に事前レンダリングすると、事前レンダリングされたページが古くなるリスクがあります。たとえば、e コマース サイトのプリレンダリング ページには、購入手続きのカート(商品がすべて入ったカート、または他のページのカート内の商品数を示すカウンタなど)が含まれている場合があります。カートに商品を追加してから、事前レンダリングされたページに移動すると、古い購入手続きの状態が表示され、ユーザーが混乱する可能性があります。

これは新しい問題ではなく、ブラウザで複数のタブを開いている場合に同じ問題が発生します。ただし、プリレンダリングされたページでは、ユーザーがプリレンダリングを意図的に開始していないため、この問題が発生する可能性が高く、予期しない問題となります。

ブラウザ内の 1 つのページからこのような更新情報を他のページにブロードキャストするには、Broadcast Channel API を使用する方法があります。これにより、複数のタブの問題も解決します。事前レンダリングされたページはブロードキャスト メッセージをリッスンできますが、有効にされるまで独自のブロードキャスト メッセージを送信できません。

または、事前レンダリングされたページは、サーバー(定期的な fetch() または WebSocket 接続を使用)を使用して更新を取得できますが、更新に遅延が生じる可能性があります。

プリレンダリングの推測をキャンセルまたは更新する

事前レンダリングされたページを更新することは、ユーザーの混乱を避けながら事前レンダリングされたページを引き続き使用するための推奨されるアプローチです。これが不可能な場合は、推測をキャンセルできます。

また、サイトがアクセスされる可能性が高い他のページをプリレンダリングする場合に、Chrome の上限内に収まるようにするためにも使用できます。

推測をキャンセルするには、ページから推測ルールを削除するか、クラスやその他の一致条件を削除する必要があります。また、推測されたページが、現在のページでなくなったことを検出すると、window.close() を呼び出すこともできます。ただし、ページでこの状態を検出できる場合は、状態を更新して最新の状態に戻すことをおすすめします。

また、これらのルール(または一致条件)を再挿入して、ページを再プリレンダリングすることもできます(ただし、通常は、無駄が少ないため、既存のページを最新の状態に保つことをおすすめします)。推測ルールが削除された後、ブラウザが削除を認識して推測をキャンセルできるように、新しいマイクロタスクで再挿入を完了する必要があります。すべての推測ルール スクリプトを削除する方法の例を次に示します。

async function refreshSpeculations() {
  const speculationScripts = document.querySelectorAll('script[type="speculationrules"]');

  for (const speculationScript of speculationScripts) {
    // Get the current rules as JSON text
    const ruleSet = speculationScript.textContent;

    // Remove the existing script to reset prerendering
    speculationScript.remove();
    
    // Await for a microtask before re-inserting.
    await Promise.resolve();

    // Reinsert rule in a new speculation rules script
    const newScript = document.createElement('script');
    newScript.type = 'speculationrules';
    newScript.textContent = ruleSet;
    console.log(newScript);

    // Append the new script back to the document
    document.body.appendChild(newScript);
  }
}

ルールを削除すると、既存のプリテンダー(またはプリフェッチ)はキャンセルされますが、ルールを再挿入すると、即時ルールまたはエアガールール(デフォルトの即時ルールを使用する URL リスト ルールを含む)のみが推測されます。ただし、中程度または保守的な推測は削除されますが、リンクが再度操作されるまで自動的に再トリガーされることはありません。

この更新オプションは、JavaScript で挿入されたルールに限定されません。HTML に含まれる静的ルールも、標準の DOM 変更であるため、同じ方法で削除または変更できます。HTTP 推測ルールは削除できませんが、一致条件(prerender クラスなど)は削除して、JavaScript で再追加できます。

また、サーバー レスポンスでプリレンダリングをキャンセルできるように Clear-Site-Header のサポートを追加することも検討しています(更新バスケット リクエストが行われた場合など)。

効果を測定する

3 つのステージ: 計画、実装、測定

推測ルールを実装した後は、速度が自動的に向上すると想定するのではなく、成功を測定する必要があります。前述のように、過剰なスペック設定は、クライアントまたはサーバーが過負荷状態になると、パフォーマンスの低下を招く可能性があります。

複数のステップ(プリフェッチ、リスクの低いプリレンダリング、早期プリレンダリング)で実装する場合は、各ステップで測定する必要があります。

成功を測定する方法

推測ルールは、LCP などの主要なパフォーマンス指標(CLS や INP にも影響する可能性があります)にプラスの効果をもたらしますが、サイト全体の指標ではその効果が明確に表れない場合があります。これは、サイトの大部分が他のタイプのナビゲーション(ランディング ページなど)で構成されているか、同じオリジンのナビゲーションがすでに十分に高速であるため、Chrome ユーザー エクスペリエンス レポート(CrUX)で報告されている 75 パーセンタイル指標に影響を与えない可能性があるためです。

CrUX のページ ナビゲーション タイプを使用すると、navigate_cache または prerender のナビゲーションの割合と、その割合が時間とともに増加しているかどうかを確認できます。ただし、詳細な分析を行う場合は、リアルユーザー モニタリングを使用して推定ナビゲーションにデータを分割し、他のナビゲーションと比較してどの程度速いかを確認する必要があります。

使用量と廃棄量を測定する方法

もう一つの重要な考慮事項は、正しいページで推測を行っているかを測定することです。これにより、無駄を省くとともに、この API から最大限の成果を得られる最適なページをターゲットに設定できます。

残念ながら、投機を開始したページでは、投機の試行のステータスを直接確認することはできません。また、ブラウザが特定の状況で推測を抑制する可能性があるため、試行がトリガーされたと推定することはできません。そのため、これらの指標はページ自体で測定する必要があります。また、ページが推測しているかどうか、または推測したことがあるかどうかを確認するために、2 つの API を確認する必要があります。

if (document.prerendering) {
  console.log("Page is prerendering");
} else if (performance.getEntriesByType("navigation")[0]?.activationStart > 0) {
  console.log("Page has already prerendered");
} else {
  console.log("This page load was not using prerendering");
}

このページは、バックエンド サーバーに推測の試行をログに記録できます。

アナリティクスの複雑さの 1 つは、プリレンダリングに対応しているプロバイダ(Google アナリティクスなど)が、ページが有効になるまでアナリティクス呼び出しを無視することです。個別のイベント呼び出しも無視されます。そのため、Google アナリティクス ユーザーは、別のオプションであるサーバーサイド ロギング オプションを使用する必要があります。

クライアントサイドで行うこともできます。この場合、各プリレンダリング ページは共有ストレージにプリレンダリングをログに記録し、呼び出し元のページがこれを読み取ります。localStorage は、ページから離れるときに読み上げることができるため、最適です(事前レンダリングされたページに対して特別な処理があるため、sessionStorage は使用できません)。ただし、localStorage はトランザクション的に安全ではなく、複数のページがプリレンダリングされている場合、他のページが同時にこの値を更新する可能性があります。このデモでは、一意のハッシュと個別のエントリを使用して、この問題を回避しています。

まとめ

推測ルールを使用すると、ページのパフォーマンスを大幅に向上させることができます。このガイドでは、この API を実装する際に考慮すべき点について説明します。これにより、潜在的な問題を回避し、API を最大限に活用できます。

実装を事前に計画することで、手戻りを回避できます。特に複雑なサイトの場合は、プリフェッチから始め、リスクの低いプリレンダリング、早期プリレンダリングへと移行する、段階的なロールアウトをおすすめします。最後に、改善点、使用量、無駄を測定して、API を最適に使用していることを確認することが重要です。