Speculative Loadingを実装することにより読み込み速度が大幅に改善するのではないかということと、合わせて仕組み上アクセス解析に不具合が出るのではないかということを懸念したため、この度この機能を詳しく掘り下げていくこととしました。
Speculative Loadingとは何か?
投機的読み込み(以下、Speculative Loadingと呼びます)とは、Chrome系のブラウザのバージョン108以降で利用が可能なブラウザのAPIである投機ルールAPI(Speculation Rules API)を活用した機能です。
具体的に言えば、ユーザーが実際にページを開く前から読込先を予測して、読み込みやレンダリングを開始する機能です。
発動条件は?
Speuclative Loadingのコードがサーバ側から出力する条件にはいくつかあり、
- WordPress 6.8以上を利用
- WordPressの管理画面にログインしていない
ことが条件となっています。
さらに、ブラウザ側でもこの機能を利用するかどうかの動作条件があります。詳しくは後述するSpeculative Loadingの構成の項目をご確認ください。
Speuclative Loadingによるメリットは?
LCP・体感速度の改善
ユーザが実際に読み込みを開始する前(設定によってはホバーした段階やそもそもページを開いた段階)から読み込みを開始するため、Largest Content Paintの数値が改善し、ひいてはCore Web Vitalsが改善する可能性があります。実際に、WordPressサイトではないものの、ShopifyでSpeculative Loadingを導入した結果最大60ミリ秒の高速化ができたことが報告されています。
さらにブラウザ側やサーバー側のキャッシュ、コンテンツの最適化も併せて適用することで、まるで一瞬で読み込まれたような体感速度を提供することも可能になります。
Speculative Loadingによるデメリットは?
Speculative Loadingはその性質上、デメリットがいくつかあります。
リソースの浪費
Speculative Loadingは、実際にクリックして表示されなかった場合、ユーザーのデータ容量や電力消費が無駄になります。
また、サーバ側でも通信が従量課金の場合にも注意が必要です。
そのため、見境なく設定することは推奨されません。
アクセスログからのアクセス件数の確認困難
さらに、リソースの浪費に加えて、Google Analyticsなどを使用しない場合、HTTPサーバからアクセスログを取得することでアクセス件数を計測することがありますが、Speculative Loadingはユーザーが実際にページを開かずとも読み込みをすることがあるため、アクセスログからの計測が困難になる恐れがあります。
また、事前レンダリングを設定する場合、ページにあるJavascriptなどまで実行されます。ですので、特別な処理をしていない場合、アクセス件数が正しく計測されない可能性があります。なお、代表的ツールであるGoogle Analyticsは対応がされているので安心して利用が可能です。
どうやって設定を最適化するか
Speculative Loadingを利用する場合、設定の最適化が重要になります。
以下のことを押さえて設定すると、デメリットを最小化しながらも効果を最大化できます。
- 特定のリンクがクリックされる確率が平均して50%以上80%未満→
prefetch
の利用を検討 - 特定のリンクがクリックされる確率が平均して80%以上→
prerender
の利用を検討 - もしクリック予測を立てられるなら…
- スマートフォンからのアクセスが多いサイト→
eager
の利用を検討- 自信がないなら
moderate
でもOK
- 自信がないなら
- パソコンからのアクセスが多いサイト→
moderate
の利用を検討
- スマートフォンからのアクセスが多いサイト→
- クリック予測を立てられない、あるいは直帰率が高いサイトの場合→
conservative
の利用を検討 - ナビゲーションバー等、ホバーされるが結局クリックされないことが多いものは除外設定
デバッグ方法
Speculative Loadingのデバッグについては、
- アクセスログを
tail -f
などを利用することでリアルタイムで確認する - ブラウザーの開発者ツールを使う
以上の二点の方法があります。今回は、よりデバッグのしやすい後者で解説します。
まずはデバッグしたいページを、サイトにログインしていない状態で開きます。
次に、ブラウザでページを開いた状態で、F12キーを押下すると、開発者ツールが開くので、Application
タブをクリックします。そして、タブが表示されたら、左側からBackground services
内にあるSpeculative loads
をクリックします。
すると、概要が表示されます。この概要には、Speculative Loadingが実行されたかどうか、何件Speculative Loadingが行われうる(あるいは行われた)かの件数が表示されます。

詳細を確認するには?
詳細を確認したい場合、Speculative loads
の横にある三角をクリックして展開し、Speculations
をクリックします。

テーブル内にある項目はそれぞれ、
URL
はSpeculative Loadingが実行されうる対象先Action
は先読みまたは事前レンダリングの別Rule set
はどこからこのルールが提供されているかStatus
は実際に先読みあるいは事前レンダリングが実行されたかの有無
を表示しています。また、Speculations
の上にあるRules
をクリックすることで、Speculative Loadingの挙動定義を確認することが可能です。

これらを確認することで、実際にSpeculative Loadingが実行されうるのか、また、先読みしすぎていないかを確認できます。
Speculative Loadingの構成
Speculative Loadingには現時点では3種類の強度(eagerness
)の設定ができます。それは、conservative
、moderate
、eager
(現在はimmediate
と同義)です。将来的にはeager
の上位にimmediate
が位置する予定となっています。
また、強度以外にも、先読みをするか、事前レンダリングをするかの選択も可能です。先読みは事前にデータは読み込むがページの表示を生成しておきません。その点、事前レンダリングは一歩踏み込み、ブラウザ側で表示を事前に生成します。
conservative
はクリックが実施された段階で初めて発動します。moderate
は、conservative
の条件に加え、対象リンクを200ミリ秒ホバーした場合でも発動します。スマートフォン等はホバーイベントが原則発生しないため、実質conservative
と同等となります。そして、eager
とimmediate
は当該Speculation Rules
が読み込まれ次第、速やかに先読みや事前レンダリングを開始するようになっています。
なお、取得を試みて、HTTP 200系以外(例: 301, 302, 401, 403, 404, 500, 502, 503など)のレスポンスコードが返ってきた場合、先読み・事前レンダリングは当該リソースにおいて無効となります。あわせて、HTTP 204あるいは205の場合、事前レンダリングのみ無効となります。
Speculative Loadingの制約
さらに、先読みと事前レンダリングの件数にも制約があります。先読みはeager
とimmediate
の場合で最大50件、事前レンダリングは最大10件までとなっています。conservative
とmoderate
の場合さらに少なく、それぞれ2件ずつまでとなります。その上限を超えると読み込まれなかったデータは古い順にメモリから削除されます。この対策により、ブラウザやサーバに過度な負担をかけないように配慮されています。そのほか先読みが実行されない代表例としては、以下が挙げられます。
- 低電力モードが有効な場合
- データセーバーが有効な場合
- メモリ不足の場合等
先ほども書きました通り、先読みは読み込まれなかった場合にネットワーク・CPU・メモリを無駄に消費します。そのため、50%以上の確率でクリックされる場合のみ利用することが推奨されます。
また、事前レンダリングはさらに負荷が高く、特別な対策(事前レンダリングを検知するコードprerenderingchange
イベントリスナーを組み込み、コード実行を遅延させるなど)がなされていない限り、アクセスログに限らず、Javascript等を利用したアクセス計測にも影響します。そのため、80%以上の確率でクリックされる場合のみ利用することが推奨されます。
WordPressでのSpeculative Loadingの実装
さて、WordPress 6.8のデフォルトテーマであるTwenty Twenty-Fiveを利用した場合、デフォルトでは以下のような構成となっています。なお、当方で改行およびインデントを入れてわかりやすくしています。
{
"prefetch":[
{
"source":"document",
"where":{
"and":[
{
"href_matches":"\/*"
},
{
"not":{
"href_matches":[
"\/wp-*.php",
"\/wp-admin\/*",
"\/wp-content\/uploads\/*",
"\/wp-content\/*",
"\/wp-content\/plugins\/*",
"\/wp-content\/themes\/twentytwentyfive\/*",
"\/*\\?(.+)"
]
}
},
{
"not":{
"selector_matches":"a[rel~=\"nofollow\"]"
}
},
{
"not":{
"selector_matches":".no-prefetch, .no-prefetch a"
}
}
]
},
"eagerness":"conservative"
}
]
}
これらが意味するところを日本語にすると、
- HTMLなどの文書のリンクをすべて先取り取得する
- ただし、以下のものは先取り取得から除外する
- WordPressの管理画面系のファイル
- /wp-content/の中のファイルのほとんど
- クエリ文字列が設定されているページ
rel="nofollow"
属性がついているリンクno-prefetch
クラスがついているリンク
- クリックしてから初めて読み込みを開始する
- 読み込みをするだけでレンダリングはしないでおく
ということです。
ルールの追加・操作
WordPressにおいて、これらの挙動を設定する先のベストプラクティスを調査したところ、まだ公表されていない模様です。ですが、筆者としては子テーマのfunctions.php
に記述することをおすすめします。これは、
- サイトごとにテーマや最適化するべき項目が異なることから、プラグインに設定するのは適切ではないこと
- 多くのサイトは既存のテンプレートを利用している(=自作ではない)ため、アップデート等で上書きされうるテーマの
functions.php
に書くことは推奨できない
ためです。
特定のページを除外したい場合、以下のようなコードを追加します:
add_filter(
'wp_speculation_rules_href_exclude_paths',
function ( $href_exclude_paths ) {
$href_exclude_paths[] = '/cart/*'; //ここを書き換える。必要に応じて行を追加し対応
return $href_exclude_paths;
}
);
//あるいは、prerenderのみ除外したい場合
add_filter(
'wp_speculation_rules_href_exclude_paths',
function ( $href_exclude_paths, $mode ) {
if ( 'prerender' === $mode ) {
$href_exclude_paths[] = '/personalized-area/*';
}
return $href_exclude_paths;
},
10,
2
);
強度を変更したい場合は以下のようなコードで対応できます:
add_filter(
'wp_speculation_rules_configuration',
function ( $config ) {
if ( is_array( $config ) ) {
$config['eagerness'] = 'moderate'; //conservativeが標準だが、moderateやeager、immediateに変更可能
$config['mode'] = 'prerender'; //prefetchが標準だが、prerenderに変更可能
}
return $config;
}
);
さらに、以下のようなコードで設定を細かく調整することも可能です:
add_action(
'wp_load_speculation_rules',
function ( WP_Speculation_Rules $speculation_rules ) {
$speculation_rules->add_rule(
'prerender', //prerenderかprefetchか
'my-moderate-prerender-url-rule', //ルール名
array(
'source' => 'list', //documentなどがあるが、対象先明示のためlist
'urls' => array(
'/some-url/', //対象URLのリスト
'/another-url/',
'/yet-another-url/',
),
'eagerness' => 'moderate', //conservative, moderate, eager, immediateから選択
)
);
$speculation_rules->add_rule(
'prerender',
'my-moderate-prerender-optin-rule',
array(
'source' => 'document', //HTMLファイル内から検索
'where' => array(
'selector_matches' => '.moderate-prerender, .moderate-prerender a', //.moderate-prerenderやそのクラスのついたリンクを対象にする
),
'eagerness' => 'moderate',
)
);
}
);