INP時代の画像読み込み:priority/fetchPriority/sizes の実戦設計(計測の流れまで)
画像のロード設計はユーザー体感を左右します。LCPを引き上げつつINPを悪化させない鍵は、優先度の分離・転送量の最小化・レイアウトの安定化です。next/imageの標準機能で十分実現できます。
先に結論
- LCP候補は priority + fetchPriority="high"。
- 折りたたみ以下は loading="lazy" + content-visibility。
- sizes を実レイアウトに合わせ、過大転送を止める。
要点(TL;DR)
- ヒーロー=priority、サブ=lazy。欲張らない。
- レイアウトの安定化(width/height/sizes, content-visibility)はINPの基盤。
- 画像自体は Progressive や LQIP と併用。
1. なぜ“優先度の分離”が効くのか
すべてを急がせるとネットワークが輻輳して本当に必要な画像が遅れます。 LCP候補をただ一つに絞り、そこだけを最優先にするのが一番効きます。
2. 最短フロー(実務)
- モバイル/PCそれぞれの LCP 候補を特定。
- ヒーローに
priority
とfetchPriority="high"
。 - 折りたたみ以下は
loading="lazy"
とcontent-visibility
。 sizes
を実レイアウトに合わせて指定。
3. 実装レシピ(コピペOK)
3.1 ヒーロー画像
// ヒーロー(LCP候補)— 最優先で取得
import Image from "next/image";
export function Hero() {
return (
<Image
src="/img/hero.jpg"
alt="Hero"
width={1600}
height={900}
priority
fetchPriority="high"
sizes="(min-width: 1024px) 1200px, 100vw"
/>
);
}
3.2 折りたたみ以下
// 折りたたみ以下— lazy + content-visibility
import Image from "next/image";
export function GalleryItem({ src, w, h }: { src: string; w: number; h: number }) {
return (
<div className="cv-auto rounded-xl overflow-hidden">
<Image
src={src}
alt=""
width={w}
height={h}
loading="lazy"
sizes="(min-width: 1024px) 400px, 50vw"
placeholder="empty"
/>
</div>
);
}
3.3 CSSユーティリティ
.cv-auto { content-visibility: auto; contain-intrinsic-size: 1 300px; }
3.4(必要時)IOでの遅延読込
// IntersectionObserver の最小実装(必要なときだけ)
// next/image の lazy で足りるのが基本。カスタムな読込制御が必要な場合のみ使用。
const io = new IntersectionObserver(entries => {
for (const e of entries) {
if (e.isIntersecting) {
// ここで画像の src を差し替える等
io.unobserve(e.target);
}
}
}, { rootMargin: "400px" });
3.5 sizesを組み立てるヘルパー
// コンテナ幅から sizes を組み立てるヘルパー(静的サイト向けの簡易例)
export function sizesFromBreakpoints(bp: { min: number; size: number }[]) {
// 例: [{ min: 1280, size: 1200 }, { min: 0, size: 100 }]
const items = bp
.sort((a, b) => b.min - a.min)
.map(x => `(min-width: ${x.min}px) ${x.size}px`);
return items.join(", ") + ", 100vw";
}
3.6 計測の流れ
- Lighthouse(モバイル)で LCP / INP / TBT を確認。
- Field(CrUXやRUM)で INP の実ユーザー値を把握。
- Network パネルでヒーローが優先取得されているか(priority/preloadの有無)。
- sizes の過大指定がないか、実レイアウトと取得解像度を照合。
4. ありがちなNGと回避策
- ヒーローを lazy → LCPが遅延。対策:ヒーローだけは
priority
とfetchPriority="high"
。 - すべてに priority → 帯域が飽和。対策:最優先は1枚、他は通常/遅延に。
- sizes を常に 100vw → 常に最大解像度を取得。対策:ブレークポイント毎に実サイズを定義。
- 凝ったJSの遅延処理 → INP悪化。対策:まずは標準の
loading="lazy"
とcontent-visibility
。
5. 公開前チェック
- ヒーローに
priority
とfetchPriority
が付いている。 - 折りたたみ以下は lazy + content-visibility。
- sizes が実サイズと合っている(転送過多なし)。
6. まとめ
“急ぐものだけ急がせる”。これだけでLCP/INPの両立はぐっと楽になります。あとは画像自体の品質(sRGB固定、Progressive)とSWR設計を揃えましょう。