Speculation Rules APIの導入
Speculation Rules APIという実験的な機能が提供され、現時点のChrome最新バージョン(v147)では主要な機能がサポートされるようになっています。
今のところFirefoxやMobile Safariなどでは機能のサポートはされていませんが、今後の期待も込めてこのサイトでも導入をしてみました。
今回はその備忘録です。
関連文書の事前取得について
prefetchやprerenderといった事前取得の概念自体は新規性のあるものではありません。
既に非推奨にはなっていますが、rel=prerenderのようにWEB標準としての事前取得・レンダリングは試行されてきた歴史があります。
僕はあまりWEB標準の歴史に明るいわけではないので、詳細はSpeculation Rules APIでウェブサイトのページ遷移を速くする- クリック前にプリレンダリングする実装手法 | ICS MEDIA あたりを読むといいと思います。(他力本願)
Speculation Rules API について
このAPIはscript要素にtype="speculationrules"を指定した上で、Speculation Rulesに準拠したJSON形式の設定を定義することで動作します。
Top-Levelの設定としてprefetchまたはprerenderを利用でき、用途に応じて使い分けることができます。
prefetch: 関連する文書リソースのみを事前取得する(その文書が参照するスクリプトや画像などのサブリソースは読み込まない)prerender: 関連する文書リソースが参照するスクリプトなどのサブリソースも含めて、事前のレンダリング処理まで行なう
そして、事前取得の条件をwhereやeagernessによって行なうことで、条件に合致するページに対して事前取得を実行できるようになります。
今回の設定
今回は僕のサイトのノート画面(/notes/{uuid})への導線となるリンクのみをprerenderの対象とするようにscript要素を用意してみました。
<script type="speculationrules" is:inline>
{
"prerender": [{
"where": { "href_matches": "/notes/([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})" },
"eagerness": "moderate"
}]
}
</script>
(is:inlineはAstroにおけるscriptの最適化を無効にするものなので、Astro以外では無視してください)
"eagerness": "moderate"は、Chromeでは「ユーザーがリンクに200ms以上カーソルを合わせた場合」に取得処理を実行するようになっています。
参考: Chrome でページを事前レンダリングしてページ ナビゲーションを即時に行う | chrome for developers
上記のスクリプトをbodyの末尾に追加することで、ノートへのリンクのある画面でリンクに200ms以上カーソルを合わせた場合に事前取得が実行されるようになります。
Chrome Dev ToolsではApplicationタブにSpecutative loadsというメニューがあり、ここから事前取得の対象になりうるURLと、それらの取得状況が確認できます。

Ready となっているレコードが「事前取得が完了していつでも爆速で遷移できるぜ!」と息巻いているリンクです。
📝MEMO: Chromeにおける事前取得の上限について

ChromeにおけるSpeculation Rules APIでの取得上限は、immediate以外では2件までとなっています。
immediateはwhereのルールに適合するリンク先の文書を即座に取得する用途のもので、基本的には遷移されることが高確率であると予期できるものに利用するものっぽいです。(乱用は危険そう)
2件以上の事前取得が実行されると、より古いものから取得情報を破棄していくようになります。
参考: Chrome でページを事前レンダリングしてページ ナビゲーションを即時に行う | chrome for developers
📝MEMO: OxlintがSpeculation Rulesの構文に対して警告をしてくる件
script要素内にスクリプトではなく直接JSONオブジェクトを差し込むという特殊な構文であるため、Oxlintのエラーが発生しました。

仕方がないのでignorePatternsでSpeculation Rulesのscriptのみを定義したコンポーネントファイルをLint対象から除外して対応しました。
僕のサイトはAstroで静的なHTMLを出力しているし、ノートは今のところ1ページあたりのコンテンツ量もさほど多くないし、prerenderをしなくても割と表示は爆速で正直なところそこまで体感として差が出る感じではなかったです。
遷移先でもAPI fetchや重ためのスクリプト処理を実行する場合などでは恩恵を強く感じられる場面もあるのかも。
WEB標準でこうしたAPIが整っていくのは非常に嬉しいので、Chrome以外の主要ブラウザの対応が進んで欲しいし何よりちゃんとstableな機能になってほしいなという気持ちになりました。今回はお祈りで締めます🙏