💹

汎用的な prefetch と prerender のための Speculation Rules 設定

2024/12/05に公開

以下の記事の内容が便利そうだったので紹介
https://csswizardry.com/2024/12/a-layered-approach-to-speculation-rules/

前半で設定内容を理解するために最小限の Speculation Rules の解説をしていますが、すでに理解していて具体的なテクニックを知りたい方は、元記事を参照するかページの最後にジャンプしてください

Speculation Rules とは

ページ内のリンクに対して事前にリクエストしておく事で、遷移時のパフォーマンスを向上するための仕組みとそれをブラウザに指示するための API です
https://developer.mozilla.org/ja/docs/Web/API/Speculation_Rules_API

注意点としては互換性がない実験的な機能であることと、事前にリクエストが走るため無駄なネットワークやサーバリソースが発生するという点です

prefetch

prefetch を指定したリンクは事前にリクエストされブラウザのキャッシュに保存されるため、遷移時にネットワークリクエストが発生せずページが表示されます。保存されるのはドキュメントのみなので CSS や JS, 画像などは保存されません

Including prefetch rules inside a <script type="speculationrules"> element or Speculation-Rules header will cause supporting browsers to download the response body of the referenced pages, but none of the subresources referenced by the page. When a prefetched page is navigated to, it will render much more quickly than if it were not prefetched.
https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API#using_prefetching

prerender

prerender を指定したリンクは prefetch に加え、事前にドキュメントの解析が行われ JS や CSS, 画像などのダウンロードや評価が実行され、これにより遷移時には即座にページが表示されます。感覚としては表示中の裏でページをレンダリングしておき遷移時にそれを利用するようなイメージです

Including prerender rules inside a <script type="speculationrules"> element or Speculation-Rules header will cause supporting browsers to fetch, render, and load the content into an invisible tab, stored in a per-document in-memory cache. This includes loading all subresources, running all JavaScript, and even loading subresources and performing data fetches started by JavaScript. Any cached prerenders and their subresources are discarded when you navigate away from the current page, except of course a prerendered document that you then navigate to.
https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API#using_prerendering

Speculation Rules の指定方法

<script> タグを使用して以下のように記述します
これによってサイト内の /articles/dbfaab6cc01982 へのリンクが事前リクエストされ、遷移時のパフォーマンスを向上させることができます

<script type="speculationrules">
  {
    "prerender": [
      {
        "urls": [ "/articles/dbfaab6cc01982" ]
      }
    ]
  }
</script>

modelate と immediate

この事前リクエストですが eagerness という属性でリクエストを実行するタイミングを指定できます。これによりブラウザやネットワーク、サーバへの負荷をコントロールすることができます

eagerness 実行タイミング
moderate リンクホバー時
immegiate ページ表示時

元記事おすすめの方法

Speculation Rules は事前リクエストする対象を明示的に指定するというアプローチになるため、ページごとに定義を変える必要がある、調整時にはコンテンツではなくヘッダの修正が必要、という管理コストがあります

これを「一括で指定する & 個別の data 属性で上書きする」というアプローチでメンテナンスしやすくするというのが今回のテクニックのアプローチのようです

記事で紹介されている仕様は以下の通りで、ルールの定義も全ページこの記述で共通のタグを設置することで反映されます

  • 基本的にすべてのリンクはホバー時に prefetch する
  • リンクごとに data-prefetch をつけて個別に制御できるようにする
    • data-prefetch=false をつけたリンクは事前リクエストしない
    • data-prefetch=prerender をつけたリンクは必ず prerender する
    • data-prefetch をつけたリンクは
      • ページ表示時に prefetch する
      • リンクホバー時に prerender する
<!--! Content by Harry Roberts, csswizardry.com, available under the MIT license. -->

<script type=speculationrules>
  {
    "prefetch": [
      {
        "where": {
          "selector_matches": "[data-prefetch='']"
        },
        "eagerness": "immediate"
      },
      {
        "where": {
          "and": [
            { "href_matches": "/*" },
            { "not": { "selector_matches": "[data-prefetch=false]" } }
          ]
        },
        "eagerness": "moderate"
      }
    ],
    "prerender": [
      {
        "where": {
          "selector_matches": "[data-prefetch=prerender]"
        },
        "eagerness": "immediate"
      },
      {
        "where": {
          "selector_matches": "[data-prefetch='']"
        },
        "eagerness": "moderate"
      }
    ]
  }
</script>

disclaimer

元記事を見かけて筋が良さそうだなと感じたので紹介していますが、実際に運用したわけではないのでどのような影響が出るかは保証できません。アプローチとしては面白いので、自分で運用する場合には参考にしたいなと思っています

Discussion