さいとブログ

Largest Contentful Paint (LCP)とnext/imageのpriorityオプションの関連について

next/imageを使用していて、ブラウザのコンソールに以下のWarningが出力される現象に遭遇しました。

warn-once.js:16 Image with src "https:/xxx.xxx.assets.com/assets/xxx/xxx.png" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.
Read more: https://nextjs.org/docs/api-reference/next/image#priority


和訳すると、

〇〇は、Largegest Contentful Paint (LCP)として検出されました。スクロールすることなく表示される領域に画像がある場合は、priorityを指定してください...


この時に初めて、Largegest Contentful Paint (LCP)という単語を目にし、気になって調べたことについて、まとめます。

3行まとめ

  • LCPとは、ユーザーが知覚できるようになるまでを計測するユーザー中心の指標のこと
  • priorityとは、preloadをするかしないかを指定するオプションのこと
  • ファーストビューで最も大きいコンテンツは、priority=trueでpreloadすることでパフォーマンス向上が見込める


Largegest Contentful Paint (LCP)とは?

web.devから引用すると、

Largest Contentful Paint (最大視覚コンテンツの表示時間、LCP) は、知覚される読み込み速度を測定するための重要なユーザーを中心とした指標です。これは、LCP がページの読み込みタイムラインにおいてページのメイン コンテンツが読み込まれたと思われる時点を示すためです。LCP を高速にすることで、そのページが便利であることをユーザーに強く印象付けることができるようになります。
引用元: https://web.dev/lcp/#what-is-lcp

知覚される読み込み速度とあるので、ユーザーが見れる状態になるまでというざっくりとした理解で良さそうです。

次に計測基準ですが、こちらもweb.devから引用します。

Largest Contentful Paint (LCP) 指標は、ビューポート内に表示される最も大きい画像またはテキスト ブロックのレンダリング時間を、ページの初期読み込み開始タイミングと比較してレポートします。

最も大きい画像またはテキストブロックとあるので、全ての要素が計測対象ではなさそうです。

ここまでを要約すると、
ブラウザのファーストビューに収まる画面内で最も大きいコンテンツ(画像など)の初期読み込み開始タイミング〜レンダリングまでの時間を計測する指標といえそうです。

priority=trueにすると、どうなるのか?

まずは、公式から引用します。

When true, the image will be considered high priority and preload. Lazy loading is automatically disabled for images using priority.
引用元: https://nextjs.org/docs/pages/api-reference/components/image#priority

和訳すると、trueの場合、画像は優先度が高いと判断され、プリロードされます。優先順位を使用している画像は、自動的にレイジーローディングが無効になります。
つまり、trueの場合、preloadされる。falseの場合、lazy loadされるようで、ロードのタイミングを指定するためのオプションのようです。

検証

当ブログのトップページを使ってpriority=true or falseによる違いを見ていこうと思います。
※前提として今回のLCPの対象はimageのため、テキストがLCPとして検出された場合とは、異なる場合があります

priority=falseの場合
priority=falseの場合
lazy loadの場合は、cssやjsを読み込んだ後にimageを読み込む挙動となっています。
正確には、ユーザーがスクロールして画像が画面に表示されたタイミングで画像の読み込みが開始されますが、今回追う対象としてしている画像は、ファーストビューに表示されるコンテンツのため、画面表示時に読み込む必要があります。
そのため、cssやjsやDOMを合わせて、レンダーツリーを構成して、画面描画をするとき(下のイメージでいうと、Paintingあたりかな?)に、「あ、画像が必要だ!!」ってなり、そのタイミングでimage読み込みが発生しているということになります。

レンダリングフローの参考としてweb.devから画像を拝借します。


priority=trueの場合
priority=trueの場合
一方、preloadの場合は、cssやjsの読み込みと同タイミングでimageを読み込む挙動となっています。
これはつまり、web.devの画像で説明すると、DOMTreeやCSSをAttachmentするタイミングで画像が既に読み込まれているということになります。

ここまでをまとめると、Paintingあたりのタイミングで画像読み込むか、レンダーツリーを構成する前に画像を読み込んでおくかで、ブラウザに表示するまでの時間を短縮できることになります。
そのため、next/imageではLCPとして検出したコンテンツは、preloadすることを推奨していると考えられます。

余談: above the foldとは?

Google Bardさんに聞くと、

Above the foldとは、Webページの表示領域の上部を指す用語です。通常、Webページはユーザーが画面をスクロールすることなく表示される領域を、above the foldと呼びます。above the foldは、ユーザーの注意を引く重要なコンテンツを配置する場所として重要です。


正式な出展がどこかは不明だが、こちらのサイトでもそのように書かれている。
https://makitani.net/shimauma/above-the-fold

プロフィール

profile icon

saitoです。
ソフトウェアエンジニアとして働いています。
web開発に関する学びを当ブログに書き残しています。