遅延読み込みがLargest Contentful Paintに実際に与える影響
遅延読み込みは有用ですが、万能のパフォーマンス改善策ではありません。LCPに対しては、どのリソースを遅らせるかによって、効くことも、悪化させることも、何も変わらないこともあります。
目次
遅延読み込みはスケジューリングの判断であり、速度を上げる魔法ではない
遅延読み込みはパフォーマンス改善として語られることがよくあります。それは、スーツケースに荷物を詰めないことが重量削減になる、という意味では正しい説明です。ブラウザーが最初に行う作業が少なくなるため、効果があります。
この違いは、通常LCPと略されるLargest Contentful Paintにとって重要です。LCPは、ビューポート内で最も大きな意味のある要素がレンダリングされるタイミングを測定します。多くのページでは、その要素はヒーロー画像です。別のページでは、大きな見出し、ポスター画像、商品写真、またはコンテンツブロックであることもあります。
遅延読み込みは、リソースがリクエストされるタイミングを変えます。画像のデコードを速くしたり、サーバーの応答を速くしたり、フォントを早くレンダリングしたりするものではありません。誤ったもの、特にLCPになる要素を遅延読み込みすると、Core Web Vitalsを満たすために表示しなければならないまさにその要素の取得を待つよう、ブラウザーに指示していることになります。
だからこそ、遅延読み込みは過剰に使われ、十分に理解されていないのです。
画像を遅延読み込みするとブラウザーは何をするのか
ネイティブの画像遅延読み込みは、通常このように追加します。
<img src='hero.jpg' loading='lazy' alt='...'>
loading='lazy'を指定すると、ブラウザーは、その画像が必要になりそうだと判断するまで取得を遅らせることができます。実際には、ブラウザーはビューポートからの距離、ネットワーク状況、画像サイズ、その他のヒューリスティックを使います。正確なルールは実装の詳細であり、変わる可能性があります。
loading='eager'の場合、または多くの場合でlazy属性がない場合、ブラウザーはその画像を通常の読み込みプロセスの一部として扱います。CSS、JavaScript、フォント、画像、その他のリクエストの間で優先順位を付ける必要はありますが、画像はすぐに発見可能です。
つまり、遅延読み込みが主に影響するのは次の3つのフェーズです。
- 発見: ブラウザーがリソースに気づくタイミング。
- リクエスト開始: ネットワーク取得が始まるタイミング。
- レンダリングタイミング: リソースを最終的にデコードして描画できるタイミング。
LCPにとって危険なのはリクエスト開始です。LCP画像のリクエスト開始が遅れると、その後のすべてが遅れてずれ込みます。
シンプルなルール: LCP候補を遅延読み込みしない
画像が初期ビューポートに表示されており、最大のコンテンツ要素になる可能性が高いなら、遅延読み込みしないでください。
これには次のものが含まれます。
- ヒーロー画像
- ファーストビュー内の主要な商品写真
- 記事冒頭の大きなリード画像
<img>として実装された背景風の大きな画像- ポスターが主要なビジュアル要素である場合の動画ポスター画像
ブラウザーは、LCP画像がリクエストされ、転送され、デコードされ、描画されるまで、その画像をレンダリングできません。遅延読み込みは最初のステップの前に不確実性を差し込みます。遅い接続では、わずかな遅延でもLCPを許容範囲から悪い状態へ押し出すのに十分なことがあります。
よくある失敗パターンは次のようなものです。
- サーバーがHTMLを送信する。
- ブラウザーがファーストビュー内の画像をパースする。
- 画像に
loading='lazy'が付いている。 - 遅延読み込みのヒューリスティックが待てると判断し、ブラウザーが待つ。
- CSSとJavaScriptの読み込みは続く。
- 画像リクエストの開始が本来より遅くなる。
- 画像ファイル自体は十分に最適化されているにもかかわらず、LCPが遅くなる。
これは厄介です。コードレビューではページがきれいに見えることがあるからです。問題はファイルサイズだけではありません。優先順位です。
ラボ出力を読みながら、LCPが本当に問題なのかを見極めようとしているなら、Lighthouseレポートを慌てず読むためのガイドは意図的に実践的に書かれています。コードを変更し始める前に、フィールドデータ、ラボのヒント、修正を切り分けてください。(注: ルーティングが大文字と小文字を区別する場合は、CMSの正確なURLを使用してください。)
訂正: 実際の内部URLを使用する
正しいWux記事のURLはHow to read a Lighthouse report without panickingです。要点は変わりません。読み込み動作を変更する前に、LCP要素を特定してください。
遅延読み込みがLCPを改善できる場合
遅延読み込みは、重要でないリソースをブラウザーの邪魔にならないようにすることで、間接的にLCPを改善できます。
ページ上部にヒーロー商品画像があり、ファーストビューより下に12枚のレコメンド画像を含むカルーセルがある商品ページを想像してください。13枚すべての画像をeagerに読み込むと、ブラウザーはユーザーがまだ見られない画像に帯域幅や接続スロットを使う可能性があります。制約のあるネットワークでは、それがヒーロー画像、CSS、フォントファイルと競合することがあります。
ファーストビューより下のカルーセル画像を遅延読み込みすると、初期ページ読み込み中に競合する重要でないリクエストが減るため、LCP画像がより早く読み込まれる助けになります。
これが、遅延読み込みの正当なパフォーマンス上の使いどころです。
- ファーストビュー内のLCP候補はeagerに読み込む
- 初期ビューポートより下の画像は遅延読み込みする
- 重要な画像を後から注入する重いスクリプトを避ける
- レイアウトシフトを避けるため、HTML内に画像サイズを保持する
遅延読み込み自体はLCP最適化ではありません。リソースの優先順位付けツールです。クリティカルパスを守るときに役立ちます。
LCP画像のよりよいパターン
ファーストビュー内のLCP画像では、ブラウザーに早く発見させ、早くリクエストさせ、レイアウトの不安定さなしにレンダリングさせることが目標です。
堅実なベースラインは次のようになります。
<img
src='/images/product-hero.avif'
srcset='/images/product-hero-800.avif 800w, /images/product-hero-1400.avif 1400w'
sizes='(max-width: 768px) 100vw, 720px'
width='1400'
height='900'
loading='eager'
fetchpriority='high'
decoding='async'
alt='Black hiking backpack with roll-top closure'
>
重要な部分は飾りではありません。
loading='eager'は遅延読み込みによる遅れを防ぎます。fetchpriority='high'は、この画像が重要であることをブラウザーに伝えます。widthとheightはスペースを確保し、レイアウトシフトを減らします。srcsetとsizesは、過大なダウンロードを防ぎます。- モダンなフォーマットは、注意深く使えば転送時間を短縮できます。
まだすべての画面に1つの大きなJPEGを配信しているなら、画像フォーマットとレスポンシブなサイズ指定のほうが、遅延読み込み属性より重要かもしれません。実践的な判断ツリーについては、AVIFがWebPに勝る場合とそうでない場合を参照してください。
背景画像には追加の注意が必要
CSS背景画像は、通常のHTML画像ほど早く発見されません。ブラウザーは、それらを知る前にCSSを取得してパースする必要があります。LCP要素がCSS背景画像なら、すでに発見を難しくしていることになります。
だからといって背景画像が禁止されるわけではありません。ただし、意図的に選ぶ必要があるということです。
装飾画像であれば、CSS背景で問題ありません。意味のあるヒーロー画像には、通常<img>または<picture>要素のほうが適しています。HTMLパーサーから見え、altテキストをサポートし、レスポンシブ画像属性とも相性がよいためです。
LCP画像にCSS背景をどうしても使う必要がある場合は、preloadを検討してください。
<link rel='preload' as='image' href='/images/hero.avif'>
preloadも魔法の杖ではありません。画像を多くpreloadしすぎると、同じ優先順位の問題が別の姿で発生します。デザインシステム内のすべての画像ではなく、本当に重要な1枚の画像に使ってください。
JavaScriptによる遅延読み込みは状況を悪化させることが多い
ネイティブの遅延読み込みが広くサポートされる前、多くのサイトはページ読み込み後、またはintersection observerの発火後にdata-srcをsrcへ差し替えるJavaScriptライブラリを使っていました。今でも使っているサイトがあります。
これは、長い記事ページや画像の多いギャラリーでは妥当な場合があります。ファーストビュー内のコンテンツには不向きです。
ブラウザーのpreload scannerは高速ですが、URLがカスタム属性に隠れている画像は、JavaScriptが実行されるまでリクエストできません。ヒーロー画像がdata-src='hero.jpg'として始まるなら、スクリプトのダウンロード、パース、実行、フレームワークのハイドレーションの後ろに発見を遅らせていることになります。
これはLCPにとって悪い取引です。重要な画像URLは実際のHTMLに置いてください。ブラウザーに仕事をさせましょう。
LCPは常に画像の問題とは限らない
ページによっては、LCP要素がテキストであることがあります。その場合、画像の遅延読み込みが直接的に大きく効くことは少ないかもしれません。ボトルネックは、レンダリングをブロックするCSS、遅いサーバー応答、クライアントサイドレンダリング、またはweb fontsかもしれません。
フォントは、テキストレンダリングが遅れる隠れた原因として頻繁に見られるため、特に触れておく価値があります。大きな見出しがLCPになることがあり、フォント読み込みの挙動が、その見出しが描画されるタイミングを遅らせたり変えたりすることがあります。画像まわりの作業で指標が動かない場合は、思い込みで進めるのではなく、LCP要素を直接調べてください。web fonts as a performance winの記事では、しばしば効く地味な修正を扱っています。ウェイトを減らす、モダンなフォーマットを使う、妥当なフォールバックを用意する、といった内容です。
自分をだまさずに遅延読み込みの変更をテストする方法
オフィスのWi-Fiでページを眺めるだけのテストはやめてください。リクエストタイミングを見る必要があります。
次のワークフローを使います。
- Chrome DevToolsを開き、Performanceトレースを記録する。
- Fast 4GやSlow 4Gなどのネットワークスロットリングを有効にする。
- キャッシュを無効にしてページを再読み込みする。
- LCPマーカーを見つける。
- LCP要素を特定する。
- Networkパネルで、そのリソースがいつ読み込みを開始したか確認する。
LCPリソースの開始が遅い場合は、理由を確認してください。
- 遅延読み込みされていたか。
- JavaScriptによって注入されていたか。
- CSS内に隠れていたか。
- 他の画像の後ろで優先度が下げられていたか。
- サーバーの応答が遅かったか。
そのうえで1つだけ変更し、再テストします。画像フォーマット、遅延読み込み、preload、JavaScriptバンドル、CDN設定を同じデプロイで同時に変更すると、パフォーマンス作業は混乱します。ページは改善するかもしれませんが、どの変更が効いたのかは分かりません。
フィールドデータも重要です。ラボツールは診断に有用ですが、LCPはデバイス、ネットワーク、ビューポート、キャッシュ状態、地域によって変わります。可能であれば、リアルユーザーモニタリングやChrome User Experience Reportのデータを使ってください。
<!-- tool-cta:start -->
💡 これを試してください: LCP 画像を小さく保ち、優先的に読み込まれるようにするために Image Compressor に通し、lazy loading を必要とせずに素早く描画されるようにしましょう。
<!-- tool-cta:end -->
ほとんどのWebサイトに向く実践的なポリシー
ほとんどのマーケティングサイト、ecommerceページ、ドキュメントサイト、パブリッシャーページでは、次のポリシーで十分です。
- ファーストビュー内の主要画像: eagerに読み込み、high fetch priorityを検討する。
- ファーストビューより下のコンテンツ画像: 遅延読み込みする。
- アイコンや小さなUIアセット: 通常は個別に深く考える価値は低い。
- CSS背景ヒーロー: HTML画像として再検討するか、慎重にpreloadする。
- JavaScriptで注入されるヒーロー画像: 可能ならレンダリングアーキテクチャを修正する。
- カルーセル: 最初に見えるスライドだけeagerに読み込み、残りは遅延読み込みする。
エッジケースはあります。ブラウザーのヒューリスティックは改善します。フレームワークは自動画像コンポーネントを追加します。ビューポート付近で検出された画像の遅延読み込みを避けるプラットフォームも出てきています。それでも原則は変わりません。重要なリソースは早く、分かりやすく。重要でないリソースは待たせるべきです。
遅延読み込みは、その違いを表現するときに価値があります。ページがすでにLCP競争に負け始めた後まで、最も重要なコンテンツをブラウザーから隠してしまうときには有害です。