本文へスキップ

コーポレートサイトの LCP を 4.1 秒から 1.2 秒にした手順

約 2 分で読めます

「サイトが遅い気がする」という相談から始まった改善作業の記録です。実測 LCP 4.1 秒のページを、構成を変えずに 1.2 秒まで縮めました。やったことは特別ではなく、計測 → 一番大きいものから順に潰すの繰り返しです。

まず計測する(推測で触らない)

最初にやるべきは、フィールドデータとラボデータの両方を見ることです。

  • フィールドデータ(実ユーザーの計測値): Chrome UX Report、Cloudflare Web Analytics など
  • ラボデータ(再現可能な計測値): Lighthouse、WebPageTest

このサイトのフィールド LCP は 4.1 秒。ラボでは 2.8 秒でした。差が出るのは、実ユーザーの回線と端末がラボ環境より遅いためです。ラボの数値だけを見て「速い」と判断しないのが重要です。

Chrome DevTools の Performance パネルで LCP 要素を特定したところ、ヒーロー画像が該当していました。ここから逆算して待ち時間の内訳を見ます。

区間 時間
TTFB 0.4s
リソース読み込み遅延 2.9s
リソース読み込み時間 0.7s
要素描画遅延 0.1s

遅延が 2.9 秒。つまり画像そのものではなく、「画像のリクエストが始まるまで」に問題がありました。

原因 1: フォントが描画を止めていた

<head> で Web フォントの CSS を同期読み込みしており、そのダウンロードが完了するまでレンダリングがブロックされていました。ブロック中はプリロードスキャナも先に進めず、画像のリクエストが後ろにずれます。

対処は 3 つ。

<!-- 1. フォントファイルへの接続を先に張る -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />

<!-- 2. 実際に使う woff2 を直接プリロードする -->
<link rel="preload" as="font" type="font/woff2" href="/fonts/inter-latin.woff2" crossorigin />

<!-- 3. LCP 画像を明示的にプリロードする -->
<link rel="preload" as="image" href="/hero.avif" fetchpriority="high" />

さらに @font-facefont-display: swap を指定し、フォント未取得でも代替フォントで描画が進むようにしました。ここまでで LCP は 2.6 秒。

原因 2: 画像が JPEG のまま 1.8 MB あった

ヒーロー画像が 2400×1200 の JPEG、1.8 MB。スマートフォンでは論理幅 390px しか使われていないのに、フル解像度を全端末に配っていました。

<img
  src="/hero-1200.avif"
  srcset="/hero-600.avif 600w, /hero-1200.avif 1200w, /hero-2400.avif 2400w"
  sizes="(max-width: 768px) 100vw, 1200px"
  width="1200"
  height="600"
  alt="オフィスで打ち合わせをする様子"
  fetchpriority="high"
  decoding="async"
/>

AVIF 化と srcset の併用で、モバイルでの転送量は 1.8 MB → 96 KB になりました。width / height を必ず入れるのも忘れずに。レイアウトシフト(CLS)の予防になります。

Astro を使っているなら <Image /> コンポーネントがこれらをまとめて生成してくれるので、自分で書く必要はありません。LCP は 1.5 秒に。

原因 3: 計測タグが 4 本入っていた

過去の施策で追加されたまま使われていないタグマネージャーとチャットウィジェットが、合計 310 KB の JavaScript を読み込んでいました。担当者に確認して 2 本を削除し、チャットウィジェットは初回スクロール後に読み込むよう変更。

// スクロールかポインタ操作があってから読み込む
const load = () => {
  const script = document.createElement('script');
  script.src = 'https://example.com/widget.js';
  script.async = true;
  document.head.append(script);
};

['scroll', 'pointerdown'].forEach((event) =>
  addEventListener(event, load, { once: true, passive: true }),
);

最終的にフィールド LCP は 1.2 秒、INP と CLS も「良好」の範囲に収まりました。

教訓

パフォーマンス改善で効くのは、たいてい次の順です。

  1. 描画を止めているもの(同期スクリプト、同期 CSS、フォント)を外す
  2. 一番大きいリソース(画像、動画)を適正なサイズと形式にする
  3. 不要なものを消す

新しいフレームワークを入れる前に、この 3 つが済んでいるかを確認するだけで、多くのサイトは十分速くなります。