思考を先に読む!Speculation Rulesでナビゲーションを瞬時にするガイド

ユーザーがウェブサイトのリンクをクリックしたとき、「読み込み中...」と表示される待ち時間は、ユーザー体験を損なう大きな要因です。この待ち時間をなくす究極のパフォーマンス改善策が、事前レンダリング(prerender)です。
しかし、事前レンダリングはリソースを大量に消費するため、「当たる」(ユーザーが実際に遷移する)リンクに絞って実行する必要があります。この問題を解決するのが、ブラウザに事前処理のルールを指示するSpeculation Rules
です。
本記事では、このSpeculation Rulesを使い、Next.jsなどのフレームワークと組み合わせて、ナビゲーションをほぼ瞬時にする方法を解説します。
この記事でわかること
Speculation Rules
の基本的な仕組みとprerender
/prefetch
の違い- Next.js App Routerでの具体的な実装パターン
- 事前レンダリングが成功したかどうかをデバッグする方法
- 帯域やリソースを無駄にしないためのルール設計のコツ
1. Speculation Rules
とは:ブラウザの先読みを制御するJSON
Speculation Rules
は、ブラウザが次にどのページに遷移するかを予測し、事前にリソースを読み込む、あるいはページ全体をレンダリングしておくためのルールを定義する仕組みです。
このルールは、HTML内にインラインで記述された<script type="speculationrules">
タグ、またはSpeculation-Rules
というHTTPヘッダーを通じてブラウザに伝えます。
主なアクションには、以下の2種類があります。
アクション | 説明 | コストと効果 |
---|---|---|
prefetch |
遷移先の文書(HTML)のみを先に取得します。 | コスト小、効果中。通信待ち時間を短縮します。 |
prerender |
遷移先のページ全体を非表示のタブでレンダリングします。HTML、CSS、JavaScript、画像などの取得から実行まで行います。 | コスト大、効果大。ナビゲーションがほぼ瞬時に完了します。 |
コストの大きさから、prerender
はユーザーが遷移する可能性が非常に高いリンクに限定して適用するのが鉄則です。
ブラウザ対応とプログレッシブエンハンスメント
現在、Speculation RulesはChromium系のブラウザ(Chrome、Edge)121以降で本格的に利用可能です。FirefoxやSafariはまだ未対応のため、あくまでパフォーマンス向上のためのプログレッシブエンハンスメントとして導入することが前提となります。
非対応ブラウザ向けには、HTMLScriptElement.supports("speculationrules")
で機能の有無を判定し、従来の<link rel="prefetch">
に切り替えるフォールバックを実装しましょう。
// Speculation Rulesのサポートを判定
if (!HTMLScriptElement.supports("speculationrules")) {
// 非対応ブラウザ向けのフォールバック処理
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = '/next-page';
document.head.appendChild(link);
}
2. 実装ガイド:Next.js App Routerでの活用
ここでは、Next.js App Router環境を想定した具体的な実装手順を見ていきます。
2-1. 最小導入(インラインrules)
app/layout.tsx
に、以下のようにspeculationrules
を定義します。これにより、サイト全体のルールを一度に設定できます。
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Next.js + Speculation Rules",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<head>
<script
type="speculationrules"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
prerender: [{
where: { selector_matches: 'a[data-prerender="true"]' },
eagerness: "moderate"
}]
}),
}}
/>
</head>
<body>{children}</body>
</html>
);
}
where
:selector_matches
やhref_matches
を使って、どのリンクを対象にするかを指定します。eagerness
: ブラウザがどのタイミングで事前処理を開始するかを調整します。
2-2. コンポーネント側での指定
先ほどのルール定義と組み合わせて、prerender
したいリンクにdata-prerender="true"
を付与します。
import Link from "next/link";
export function ProductCard({ id, title }: { id: string; title: string }) {
return (
// ユーザーがクリックしそうなリンクにだけ指定
<Link href={`/products/${id}`} data-prerender="true">
<h3>{title}</h3>
</Link>
);
}
3. 配信方法とセキュリティ
Speculation-Rules
ヘッダーでの配信(推奨)
大規模サイトでは、ルールを外部JSONファイルとして管理し、Speculation-Rules
ヘッダーで配信するのが効率的です。
- JSONファイルの作成:
rules/spec.json
のようなファイルを作成し、ルールを記述します。 - MIMEタイプ: サーバー設定で、このJSONファイルのMIMEタイプを
application/speculationrules+json
に設定します。 - HTTPヘッダー: ページのレスポンスヘッダーに
Speculation-Rules: /rules/spec.json
を付与します。
CSPと同一オリジン制限
- CSP: インラインの
<script>
タグを使う場合は、Content-Security-Policy: script-src 'self' 'inline-speculation-rules' ...
を追加します。 - 同一オリジン制限:
prerender
は基本的に同一オリジン(same-origin)のページに限定されます。同一サイト(same-site)のクロスオリジンの場合でも、遷移先のサーバーがSupports-Loading-Mode: credentialed-prerender
ヘッダーで明示的にオプトインしなければprerender
は実行されません。クロスサイト(cross-site)の事前レンダリングは完全に不可です。
4. サーバー側での検知と制御
投機的なプリロードは、サーバー側から見ると通常のアクセスと区別がつきにくいことがあります。Sec-Purpose
ヘッダーを使って、ログの分離やリソースの制御を行いましょう。
- ログの分離:
prerender
やprefetch
によるリクエストには、Sec-Purpose: prefetch;prerender
ヘッダーが付与されます。サーバー側でこのヘッダーを検知し、通常のアクセスログとは分けて集計することで、リソースの消費状況を正確に把握できます。 - キャッシュのクリア: 開発時や本番運用で問題が発生した場合、
Clear-Site-Data: "prefetchCache", "prerenderCache"
ヘッダーを送信することで、ブラウザの投機結果キャッシュを強制的にクリアできます。
安全な除外ルールの具体例
カート追加やログアウトなど、ユーザー状態を変更する可能性のあるページは、誤ったprerender
を防ぐためにルールから明示的に除外すべきです。
{
"prerender": [
{
"where": {
"selector_matches": "a[data-prerender='true']"
},
"href_matches": ["/*"]
}
],
"prerender_not_for_href_matches": ["/logout", "/cart/*", "/checkout/*", "?add-to-cart=*"]
}
また、requires
プロパティを使って、クロスオリジンのリソースを匿名クライアントからのアクセスに限定するなどの制御も可能です。
5. デバッグと「動かない時」の一次切り分け
DevToolsでの確認
Chrome DevToolsのApplication → Speculative loadsパネルは、事前レンダリングのデバッグに欠かせません。成功・失敗のステータスだけでなく、なぜ失敗したのかの理由(例: Prerendering was cancelled because a popup was opened.
)もここで確認できます。
動かない時のチェックポイント
- ブラウザ設定: Chromeの「ページをプリロードする」設定がオフになっていないか確認しましょう。
- メモリ・バッテリー: ユーザーのデバイスが低メモリ状態だったり、バッテリーセーバーが有効になっていたりすると、ブラウザは
prerender
を抑制することがあります。 - 機能制限:
prerender
中はalert()
などのポップアップ系APIが無効化されます。ログインフォームなど、インタラクションが必須なページはprerender
の対象から外しましょう。また、cross-origin
のiframe
はアクティベーションされるまでレンダリングが遅延されるため注意が必要です。
まとめ:Speculation Rules導入チェックリスト
「当たるリンクだけをprerender」――これが要点です。小さく始めて計測し、効果が出た導線にだけ段階的に適用。下のチェックリストで、安全に導入を完了させましょう。
-
prerender
やprefetch
のルールは、selector_matches
で意図の高いリンクのみを対象にする。 - CSPに
'inline-speculation-rules'
を追加するか、ヘッダー配信にする。 -
Speculation-Rules
ヘッダーを配信する場合は、MIMEタイプをapplication/speculationrules+json
に設定する。 -
href_matches
やprerender_not_for_href_matches
でログアウトやカートなど副作用のあるURLを明示的に除外する。 - Chrome DevToolsと
Sec-Purpose
ヘッダーを使って、正しく機能しているか検証する。 - 非対応ブラウザ向けに、
HTMLScriptElement.supports()
を使ったフォールバック処理を実装する。
この記事が、あなたのウェブサイトのナビゲーション速度改善の一助となれば幸いです。ご覧いただきありがとうございました。