< BACK 大規模サイトのCore Web Vitals:1.5秒以下のLCPを達成する方法 -- ラインアート イラスト

大規模サイトのCore Web Vitals:1.5秒以下のLCPを達成する方法

2022年、ホスティング比較サイトが私の元に届いた。大規模なカタログ、約4,000ページ、深くネストされたカテゴリ構造、あちこちに散らばったアフィリエイトリンク、小大陸ほどのサイズのヒーロー画像。Google Search Consoleは悪夢のような状態だった。LCPはモバイルで4.2秒。INP(当時はまだFIDと呼ばれていた)は危険水準。クライアントは既に前の代理店に6,000ポンドを費やしており、彼らはCDNを導入してそれで終わりにしていた。

そのプロジェクトは、Seahawkで高ページ数サイト、ディレクトリサイト、リスティングプラットフォーム、HostList風のビルドのようなホスティングレビュープロパティに対するパフォーマンスへの考え方を形作ることになった。以下は実際のプレイブックだ。performance at Seahawk for high-page-count sites, directory sites, listing platforms, hosting review properties like HostList-style builds. What follows is the actual playbook.

---

大規模サイトがLCPを異なる方法で低下させる理由

小規模なサイトは単純な問題を抱えています。1つのヒーロー画像、1つのテーマ、やりすぎている1つのプラグイン。この3つを修正すれば2秒以下になります。

大規模サイト?まったく別の動物だ。LCP要素はページによって変わる。カテゴリアーカイブは、プロダクト詳細ページとは異なるLCP候補を持ち、それはホームページとは異なる候補を持つ。ほとんどのパフォーマンスツールは単一のスコアを報告する。その数字は嘘だ。ワイルドに異なるページセットの平均値であり、ホームページを修正しながら下にある3,800のリスティングページを無視することは、代理店が悪い評判を得る正確な方法だ。which page you're on. A category archive has a different LCP candidate than a product detail page, which has a different candidate than the homepage. Most performance tools report a single score. That number is a lie, it's an average of a wildly varied set of pages, and fixing the homepage while ignoring the 3,800 listing pages underneath it is exactly how agencies earn bad reputations.

GoogleのCore Web Vitals文書は、フィールドデータ、つまり実ユーザーが経験するもので、Chrome User Experience Reportで測定されるものが、Googleが実際にランキングシグナルに使用するものであることを明確に述べている。PageSpeed InsightsからのラボデータはDirectional(方向性)であり、確定的ではない。PSIで95点を取っておきながら、CrSXデータでは依然としてPoor LCPを示しているサイトを見たことがある。この2つを混同しないこと。Core Web Vitals documentation from Google is clear that field data, what real users experience, measured in Chrome User Experience Report, is what Google actually uses for ranking signals. Lab data from PageSpeed Insights is directional, not definitive. I've seen sites score 95 on PSI and still have Poor LCP in CrSX data. Don't confuse the two.

リスティングサイト上の3つの本当の原因

私が監査してきた(この時点で数百件を通過してきた)すべての大規模サイトで、LCP障害はほぼ毎回、3つの根本原因にさかのぼる。

  • 最適化されていないヒーローまたはカード画像。フル解像度で提供されることが多く、形式が間違っており、fetchpriorityヒントがない。, often served at full resolution, wrong format, no fetchpriority hint
  • レンダリングをブロックするサードパーティスクリプト、アフィリエイトトラッカー、広告ネットワーク、ブラウザが何かをペイントする前にロードされる比較ウィジェット, affiliate trackers, ad networks, comparison widgets loading before the browser can paint anything
  • LCP予算を膨らませるTTFB。ページがロード開始する前に600~900msを消費する低速なサーバーレスポンス, slow server response eating 600-900ms before the page even starts loading

3番目のは人々が過小評価するものだ。TTFBが700msなら、ブラウザが単一のピクセルをレンダリングする前に、既に「Good」LCP予算の約半分を費やしている。ホスティング選択とサーバー側キャッシング動作は、DevOpsの懸念ではなく、SEOの懸念だ。

---

TTFBから始める:これは第一にホスティングとキャッシング機構の問題だ

上で言及した HostList タイプのプロジェクト?最初にやったことは5つの異なる地理的位置から WebPageTest を実行することだった。TTFB は常に680~820msだった。そのサイトはバージニア州の共有ホスト上にあった。オーガニックトラフィックのほとんどは UK と Germany から来ていた。WebPageTest from five different geographic locations. TTFB was consistently 680-820ms. The site was on a shared host in Virginia. Most of their organic traffic came from the UK and Germany.

マネージドWordPressホストに移行し、ロンドンとフランクフルトにエッジノードを配置しました。リスティングページに12時間のキャッシュ有効期間を設定したフルページキャッシングを構成しました(データはそもそもそんなに頻繁には変わらなかったので)。TTFBはリピートリクエストで120~180ms、初回キャッシュミスで280~350msに低下しました。この単一の変更により、画像に手を加える前にLCPがおよそ500ms改善されました。WordPress host with edge nodes in London and Frankfurt. Configured full-page caching with cache lifetimes of 12 hours on listing pages (the data didn't change that often anyway). TTFB dropped to 120-180ms on repeat requests, 280-350ms on first-hit cache misses. That single change shaved roughly 500ms off LCP before I touched a single image.

ホスティング側で常にチェックすることがいくつかある:

  1. フルページキャッシングは実際に機能しているか?X-Cacheレスポンスヘッダーを確認する。すべてのリクエストでMISSと表示されている場合、キャッシング層は機能していない。 Check the X-Cache response header. If it says MISS on every single request, your caching layer isn't functioning.
  2. オリジンサーバーは主要な対象ユーザーに地理的に近いか?これは明らかに聞こえるが、実際には間違っていることが意外と多い。 This sounds obvious. You'd be surprised how often it's wrong.
  3. キープアライブは有効になっているか?安いホストの中には、まだ永続接続を無効にしているところがある。2024年にこんなことがあるとは信じられないが、起きている。 Some cheaper hosts still disable persistent connections. Wild in 2024, but it happens.
  4. HTTP/2またはHTTP/3は有効か?curl -I --http2 https://yourdomain.comを実行して、レスポンスのプロトコルを確認する。 Run curl -I --http2 https://yourdomain.com and check the protocol in the response.

TTFBを解決するまで画像最適化に手を付けるな。遅いサーバー上で画像を最適化するのは、燃えている家を塗装するようなものだ。

---

LCP画像問題(そして`fetchpriority`がすべてを変える理由)

そうだ。画像だ。カードグリッドレイアウトを持つリスティングサイトでは、LCP要素はほぼ常に最初のビューポート上部のカード画像、またはヒーロー画像だ。ブラウザはそれを発見し、取得し、デコードし、レンダリングしなければならない。これらの各ステップは遅延する可能性がある。

HostListプロジェクトで実際に行ったことを順番に説明します。

  1. すべてのカード画像をWebPに変換し、Imagifyのバルク変換機能を使用しました。ファイルサイズは平均58%削減され、使用していたカードサムネイルサイズ(280×180px表示、Retina対応で2倍配信)では目に見える品質低下はありません。, using Imagify's bulk conversion. Average file size dropped 58% without visible quality loss at the card thumbnail sizes we were using (280×180px display, served at 2x for retina).
  2. 最初のカード画像に`fetchpriority="high"`を追加しました。この1つの変更だけでWebPageTestで測定したLCPから約200ms削減されました。ブラウザはそれを通常の遅延読み込み画像として扱わなくなり、プリロードスキャナーで即座にキューに入れます。, This one change alone knocked ~200ms off measured LCP in WebPageTest. The browser stops treating it like a regular lazy image and queues it immediately in the preload scanner.
  3. カード画像の最初の2行から`loading="lazy"`を削除しました。遅延読み込みはビューポート下の画像には優れていますが、最初の表示行では実際に害になります。ブラウザに対し、既にビューポート内にある画像をビューポート付近までは取得しないよう指示するからです。, Lazy loading is brilliant for below-fold images. On the first visible row, it actively hurts you. It tells the browser to not fetch the image until it's near the viewport, which it already is.
  4. ホームページテンプレートに限定して、`<head>`内のヒーロー画像用に`<link rel="preload">`タグを追加しました。 in the <head> on the homepage template specifically.

このシーケンスにより、ホームページのLCPがラボ環境で3.1sから1.4sに短縮されました。フィールドデータは約28日以内に続きました(CrUXデータが大規模な変更を反映するのにはおおむねそのくらいかかります)。

レスポンシブ画像に関する注記

モバイルデバイスに1400px幅の同じ画像を配信していたら、帯域幅を浪費して復号化時間を増やしています。srcsetを正しく使用してください。2016年の話題に聞こえるかもしれませんが、Seahawkを通過するサイトの約40%で未だにこれを見かけます。WordPressの`wp_get_attachment_image()`関数はsrcsetを自動生成しますが、画像が十分な解像度でアップロードされており、テーマが`add_filter('max_srcset_width', ...)`で抑制していない場合に限ります。srcset properly. I know this sounds like a 2016 conversation but I still see it on probably 40% of the sites that come through Seahawk. The WordPress wp_get_attachment_image() function generates srcset automatically, but only if the image was uploaded at sufficient resolution and the theme hasn't suppressed it with add_filter('max_srcset_width', ...).

---

レンダリングをブロックするスクリプト:アフィリエイトサイトの税金

ホスティング比較サイトとリスティングプラットフォームはアフィリエイト収益で成り立っています。つまりサードパーティトラッキングスクリプトが必要です。Commission Junction、Impact、Awin、カスタムピクセルトラッカー、これらが積み重なります。単一のリスティングサイトで14個の異なるサードパーティスクリプトオリジンをカウントしたことがあります。それぞれがスクリプトの1バイトも受信される前にDNSルックアップ、TCP接続、TLSハンドシェイクです。

解決策はスクリプトを削除することではありません。できません、収益がそれに依存しています。解決策はシーケンシングです。

サードパーティスクリプトがLCP要素の初期レンダリングをブロックすることは絶対にあってはならない。完全に。

実践的には、これは以下を意味する:

  • すべてのアフィリエイト/アナリティクススクリプトを、<head>ではなくDOMContentLoadedイベント後にロードするよう移動させる。after the DOMContentLoaded event, not in <head>.
  • 制御下にあるすべてのスクリプトにasyncまたはdefer属性を使用する。async or defer attributes on every script you control.
  • 制御していないスクリプト(タグマネージャーで注入されるもの)については、Google Tag Manager自体をdeferで読み込みます。はい、これはほとんどのアフィリエイトトラッキングユースケースで安全ですし、GTMの公式ドキュメント自体がこのアプローチを認めています。defer, yes, this is safe for most affiliate tracking use cases, and GTM's own documentation acknowledges this approach.
  • Asset CleanUp Proやwp Rocketのスクリプト遅延機能などのスクリプトマネージャーを使用して、ユーザーインタラクション(最初のスクロールまたは最初のクリック)まで非必須のサードパーティをdeferする。

HostListの再構築では、サードパーティスクリプトをdeferすることでTotal Blocking Timeを1,840msから290msに削減した。TBTは直接的なCore Web Vitalではないが、そのCore Web VitalであるINPとの相関が強い。is.

フォント読み込み:誰も言及しない静かなLCP殺し

フォント読み込み:誰も言及しない静かなLCP殺し

カスタムフォントは特定の不具合モードを引き起こします。ブラウザはレイアウトをレンダリングし、LCP テキスト要素に到達し(LCP が画像ではなく見出しの場合もあります)、その後フォントファイルがペイントされるまで待機します。これはFlash of Invisible Textと呼ばれ、フォントファイルのサイズとサーバーの近接性に応じて、LCP を200ミリ秒から1秒以上遅延させます。

この問題を解決するには2つの方法があります:

  • `@font-face`宣言に`font-display: swap`を指定します。ブラウザはフォールバックフォントで即座にレンダリングし、カスタムフォント読み込み時にスワップします。LCP候補が時間内に描画されます。 in your @font-face declaration, the browser renders in a fallback font immediately and swaps when the custom font loads. LCP candidate gets painted on time.
  • フォントを自分でホストしてください。Google Fonts は クロスオリジンリクエストを追加します。google-webfonts-helperツールを使用した自己ホスティングにより、独自ドメインからフォントを配信でき、その余分な接続を削減できます。google-webfonts-helper tool lets you serve fonts from your own domain, cutting that extra connection.

大規模なディレクトリサイトをそのツールを使用してGoogle Fonts から移行するのに約45分かかりました。LCP が180ミリ秒改善されました。単体では革新的ではありませんが、他のすべての施策と組み合わせると、これらのマージンが複合的に効いてきます。

---

フィールドで実際に重要なものを測定する

CrUX データが最高の真実です。しかし月1回の更新に限定され、十分なトラフィックのある URL のみです。数千ページのある大規模サイトの場合、より細粒度な何かが必要です。

PageSpeed Insights APIを代表的なURLサンプル全体でスクリプト化して使用しています。通常はトラフィック上位100ページ、50個のカテゴリーレベルページ、20個の「薄い」深いカタログページです。月次実行により、単一ポイントスコアではなく適切なパフォーマンス分布が得られます。PageSpeed Insights API scripted across a representative sample of URLs, typically the top 100 pages by traffic, 50 category-level pages, and 20 "thin" deep-catalogue pages. Running this monthly gives a proper performance distribution, not a single-point score.

Lighthouse CI(クライアントの開発サイクルがある場合、CI/CDパイプラインで実行)では、以下の値に対してアサーションを行っています:

  • ラボ環境ではLCP ≤ 2.5秒(フィールドがラボより10~15%遅延する傾向があるため保守的な目標)
  • TBT ≤ 300ms
  • CLS ≤ 0.1

ただし正直なところ、目標がLCP 1.5秒未満のHostListタイプのビルドの場合、ラボターゲットはより厳格である必要があります。これらのプロジェクトではLighthouse CIでLCP ≤ 1.8sを設定しており、CrUXが追いつけば通常はフィールドデータで1.3~1.5s のLCPが生成されます。

---

まとめ:HostListの結果

以上のすべてを実行した後——ホスティング移行、フルページキャッシング、画像フォーマット変換、LCP候補に対するfetchpriority、above-foldの行からのlazy-load削除、スクリプト遅延実行、フォント自己ホスティング——数字は次のようになりました:fetchpriority on LCP candidates, lazy-load removal from above-fold rows, script deferral, and font self-hosting, here's what the numbers looked like:

  • TTFB: 780ms → 160ms(中央値、英国訪問者): 780ms → 160ms (median, UK visitors)
  • LCP(ラボ、モバイル):4.2秒 → 1.4秒: 4.2s → 1.4s
  • LCP(フィールド、CrUX、75パーセンタイル):3.8秒 → 1.6秒(移行後60日時点で測定): 3.8s → 1.6s (measured 60 days post-migration)
  • TBT:1,840ms → 290ms: 1,840ms → 290ms
  • CLS:既に0.03で良好なため、変わらず: was already fine at 0.03, unchanged

すべてのサイトが2.8秒の改善を得られるわけではありません。しかし、私が携わった大規模なリスティングサイトのほぼすべてが、これらの問題を同時に抱えていました。つまり、改善効果が積み重なるということです。1つ修正すれば300msの改善が得られます。すべて修正すれば2.5秒の改善が得られます。

---

よくある質問

ホスティングは本当にLCPに大きく影響するのですか?

はい、おそらく最初は何よりもそれが大切です。TTFBが500msを超えている場合、どれだけ画像を最適化しても「Good」なLCPには到達しません。TTFBはすべてが成り立つ基盤です。まず200ms未満に抑えてから、その他のことについて心配してください。

ホスト移行ではなくCDNを使うべきですか?

CDNはスタティックアセットの配信に役立ち、適切に設定すればキャッシュされたフルページHTMLのTTFBを削減できます。しかし多くのCDNセットアップはアセットのみをキャッシュし、フルHTMLレスポンスはキャッシュしません。CDNが実際にキャッシュされたHTMLを配信しているのか、単に画像をオフロードしているだけなのかを確認してください。後者の場合、より優れたオリジンホストのほうがLCPに大きく貢献します。

`fetchpriority="high"`は今、広くサポートされていますか?

2024年現在、Chrome、Edge、Safari(Safari 17.2以降)でサポートされています。FirefoxのサポートはFirefox 132で実装されました。それをサポートしていないブラウザでは安全に無視されます。LCP画像要素に追加することに悪い点はありません。

CrUXデータが改善を反映するのにどのくらいの時間がかかりますか?

ユーザーが実際により高速化したサイトを利用開始してからおよそ28日です。CrUXは28日間のローリングウィンドウを使用します。今日変更をデプロイすれば、フィールドデータスコアは約1ヶ月間、完全にはそれを反映しません。最適化スプリントの翌日にPageSpeed Insightsがまだ「改善が必要」と表示されていても慌てないでください。

リスティングサイトにとって最も高いインパクトをもたらす単一の変更は何ですか?

ほぼすべてのプロジェクトで最大の要因はTTFBです。ただし2番目に高い要因は一貫してファーストビューのカード画像からloading="lazy"を削除し、fetchpriority="high"を追加することでした。この2つで通常、LCP改善全体の40~60%を占めています。その他すべては基礎の上に積み重なった複利的な改善です。loading="lazy" from above-fold card images and adding fetchpriority="high". Together those two things usually account for 40-60% of the total LCP improvement. Everything else is compounding gains on top of that foundation.

---

大規模サイトのパフォーマンス作業は、ほぼ配管工事です。地味で、系統立っていて、4秒のLCPを1.4秒まで短縮し、2ヶ月後にオーガニックトラフィックが増加するのを見守るときは非常にやりがいがあります。単一の魔法の設定はなく、正しい順序で下した一連の具体的な決定があるだけです。

サーバーを速くしましょう。次にLCP要素を早期に発見されて、フェッチされるようにしましょう。そして他のすべてをその邪魔にならないようにしましょう。

< BACK