記憶に残ったことを忘れないために色々メモとしてのこしていきます

Optimizing resource loading with Priority Hints の和訳

対象の記事はこちら👉Optimizing resource loading with Priority Hints
Priority Hints について分かり易い記事が web.dev で投稿されていたので、和訳をしてみる。
コンテキストが抜けている部分は補って意訳していく。それではスタート!

導入

Priority Hints によって、ブラウザはリソースの読み込み優先度を知ることができるようになり、リソースの読みこみが適切に制御可能となった。それによりCore Web Vitalsのスコアが以前よりも改善しやすくなった。

ブラウザがウェブサイトを解析し、画像・JS・CSSのようなリソースをダウンロードし始めるわけだが、その際最適な順番で読み込みの順番を制御している。ではどのように制御されているのかだが、各リソースに対して fetch priority が割り当てられている。この priority は次の2つによって決められている。

  • リソースの種類
  • リソースの位置 in document

例えば、ビューポート内の画像であれば「High」priority、レンダーブロッキングな head 内のCSSについては「Very High」な priority といったように、ブラウザがよしなに付与してくれる。このようにブラウザは priority の付与を自動的にしてくれるわけだが、全てのケースにおいて最適な priority を付与してくれるかといえば、そうとはいえない。

この記事では、Priority Hints と fetchpriority 属性についてまとめていく。

概要

Priority Hints によってできること、以下3つ。

  • fetchpriority="high" を画像要素に付与することで、 LCP (メインコンテンツの読み込み時間をはかる指標。ユーザーがページコンテンツとインタラクションをとれるようになるまでの時間と関連している)の最適化が可能になる
  • async script の priority を上げることができる。現在は <link rel="preload">async script に付与する hack が使われている
  • 即時に読み込まなくても良いリソースの priority を下げることで、画像の読み込み順序を最適化する


これまでリソースの priority の投機的取得には preloadpreconnect という制限された手法を使わざるを得なかった。 Priority Hints はこれらの「Resource Hint」を補完することができるのだが、ここで一旦 preloadpreconnect について復習しておこう。
preload : 先読みしておきたいクリティカルなリソースを、ブラウザに対して通知する機能である。preload を設定しない場合、読み込み順序の遅くなるリソース、例えば、スタイルシートの中のフォントや背景画像、JSから読み込まれる画像に対して価値を発揮することができる。
preconnect : コネクションを温めておき (=DNS の解決 + TCP の接続まで確立しておくことで、リクエストをすぐに送ることができる)、 Time-to-first-byte を改善できる。完全なリソースのURIは把握していないが、origin を知っている場合に有効な方法。

Priority Hints は fetchpriority を使って利用することができる。HTMLだけではなく、JSの fetch メソッドの priority プロパティでも制御は可能だ 例: fetch('/api/articles.json', { priority: 'high' }).then(/.../) 。 Priority Hints は preload も補完することもできる。LCPの画像は preload された場合でも優先度が低くなってしまうが (←コメント: 仕様なのかは不明)、Priority Hints を使うことで読み込み順を早めることが可能となる。

リソースの優先度 (priority)

priority に影響する要素について以下のようなものが挙げられる。

  • CSS、フォント、JS、画像、サードパーティリソースには別々の priority が付与される
  • documentのどこにリソース対象のコンテンツが位置しているかによって priority が付与される
  • preload を使うことで、ブラウザに対象のリソースの検知を促進する
  • priority の順序は asyncdefer によって影響を受ける

それぞれのリソースに対する priority については、こちらの参照をおすすめする(個人的には、納得感のある priority で設定されていると感じた)。priority が同じリソースについては、検知された順に読み込まれていくようだ。ちなみにChrome の Devtool で priority は確認できる。


どこで Priority Hints を使うのか?

リソースの読み込みについて、下記のようなことはご存知かとおもう。

  • ブラウザが検知しづらいリソースについては preload を使うことで priority を上げることができる
  • async defer をつかうことで他リソースのブロッキングを防ぐことができる
  • below-the-fold content (ファーストビューより下に位置するコンテンツのこと) についてはLazy Loadを使うことで、重要な above-the-fold content (ファーストビューのコンテンツ) に帯域幅を優先的に割り当てることができる


一方で、上記では不十分なケースについて次のようなものがある(= Priority Hints が出番となる)

  • above-the-fold content に priority の異なる画像が複数ある。例えば、カルーセルの画像では先頭の画像の priority を高くしたい
  • ビューポートの中のヒーロー画像が「Low」priorityである。レイアウトが完成したのち、Chromeは画像がビューポートにあることを検知し、priority を高くする(Devtoolは最終的な priority のみを出力する – WebPageTestは両方出力してくれる )。これにより大きな読み込み遅延が発生してしまう。画像に対して 「High」priority を付与することで、解決することができる。補足だが、preload で priority を高くするためには、LCP画像の早期検知と fetchpriority='high'が必要になる。その2つが満たされない場合、「Low」priority となってしまう。補足: ビューポート外の画像は「Low」priority が付与されるが、レイアウトでビューポート内に入ることがわかると「High」にブーストされる。
  • <script>async defer を付与することで、非同期の読み込みができるが、これらはデフォルトでは「Low」priority が付与される。つまり非同期でも優先度を上げて読み込みをしたい場合は Priority Hints が必要となる。
  • JSの fetch メソッドで読みこまれるリソースは「High」priority である。しかし、優先度を落としたいときは Priority Hints を使う必要がある。
  • CSSとフォントには「High」 priority が付与されるが、場合によっては LCP 画像を優先的に読み込ませたいときがある。


fetchpriority属性

img script link iframe に使うことができる。

<!-- We don't want a high priority for this above-the-fold image -->
<img src="/images/in_viewport_but_not_important.svg" fetchpriority="low" alt="I'm an unimportant image!">

<!-- We want to initiate an early fetch for a resource, but also deprioritize it -->
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<script>
  fetch('https://example.com/', {priority: 'low'})
  .then(data => {
    // Trigger a low priority fetch
  });
</script>

<!-- The third-party contents of this iframe can load with a low priority -->
<iframe src="https://example.com" width="600" height="400" fetchpriority="low"></iframe>


fetchpriority を適用した場合のユースケースについては元記事を参照

Priority Hints利用時の留意点

  • fetchpriority はヒントであり、ディレクティブではない。ブラウザはディベロッパーの設定を尊重はするが、かならずしもそれに従うわけではない
  • Priority Hints と preload の違いを理解しよう。
    • preload は強制的な fetch であり、ヒントではない
    • preload はブラウザにリソースの早期検知を促すものの、fetch についてはデフォルトの priority に従う。Priority Hints についてはリソースの検知は促さないが、priority を調整できる。
    • preload のほうが検証しやすい
  • Priority Hints を使うことで priority を調整し preload を補完することができる。すでにLCPの画像を <head> で preload 指定している場合、「High」priority は大きな効果をもたらさないだろう。しかしもし、preload 対象のリソースがdocumentの下部に記載されている場合 (ビューポートの外)、「High」priorityは効果を発揮する。