2026年のCore Web VitalsのためのNext.js画像最適化
過去4年間、Next.jsアプリケーションの画像最適化に取り組んできた。率直に言うと、2026年のランドスケープはnext/imageが最初にリリースされた時代とは全く異なっている。Googleの Core Web Vitals の閾値は厳しくなり、新しい画像形式は成熟し、next/imageコンポーネント自体も何度か書き直されている。2023年と同じ方法で画像を設定している場合、パフォーマンス(とランキング)を台無しにしている。
これはNext.jsのドキュメントの焼き直しではない。LCPスコアが実際に重要な本番サイトを数十個デプロイしてから学んだことだ。画像読み込みで200msの差が1ページ目と3ページ目の違いを生んだ場合もある。
目次
- 2026年のCore Web Vitals: 何が変わったのか
- next/imageが実際にどのように動作するか
- LCP問題: ヒーロー画像がスコアを台無しにしている理由
- フォーマット戦争: 2026年のAVIF対WebP対JPEG XL
- レスポンシブ画像を正しく実装する
- CDNとエッジ最適化戦略
- 重要なものを測定する: ツールとベンチマーク
- 実際に成果を生む高度なテクニック
- すべての監査で見かける一般的な間違い
- FAQ

2026年のCore Web Vitals: 何が変わったのか
Googleは2025年末にCore Web Vitalsの閾値を更新した。変更は些細なものではなかった。現在の状況は以下の通り:
| メトリクス | 2023年「良好」閾値 | 2026年「良好」閾値 | 測定内容 |
|---|---|---|---|
| LCP | ≤ 2.5秒 | ≤ 2.0秒 | Largest Contentful Paint |
| INP | ≤ 200ms | ≤ 150ms | Interaction to Next Paint |
| CLS | ≤ 0.1 | ≤ 0.1 | Cumulative Layout Shift |
| TTFB | N/A (Core Web Vitalsではない) | 非公式に≤ 600ms | Time to First Byte |
LCP閾値が2.5秒から2.0秒に低下したことは、画像が多いサイトに最も大きな影響を与えた。0.5秒は大したことないように聞こえるが、60%以上のページではLCP要素が画像である。通常、ヒーロー画像、商品写真、または特集記事のサムネイルである。
INP(FIDの後継)はすでに採用されていたが、150msという厳しい閾値は、設定が悪いレイジーロード・スクリプトを含む重いJavaScriptバンドルがインタラクティビティのスコアを下げることを意味する。
CLSは同じままだったのは朗報である。ただし、画像は明示的なディメンションを持たない場合のレイアウトシフトの第一の原因のままである。
なぜこれがNext.js固有に重要なのか
Next.jsアプリは性質上JavaScriptが豊富である。Reactを配信し、フレームワークコードを配信し、注意しなければ画像最適化ロジックまでクライアント側に配信している。React アプリのより厳しいLCPバジェットと JS オーバーヘッドの組み合わせは、静的HTMLサイトより間違える余地が少ないことを意味している。
これがまさにNext.js開発に焦点を当てる理由である。フレームワークは信じられないようなツールを提供するが、それを正しく設定する方法を知っている場合のみである。
next/imageが実際にどのように動作するか
next/imageの<Image />を使う時に何が起こるかを解明しよう。パイプラインを理解することで、より良い最適化判断ができる。
リクエストフロー
- ビルド時: Next.jsは
/_next/image?url=...&w=...&q=...を指すimg`タグを含むHTMLを生成する - 初回リクエスト: Next.jsの画像最適化APIがリクエストを受け取り、元の画像をフェッチし、リサイズし、形式を変換し、結果をキャッシュする
- その後のリクエスト: キャッシュされたバージョンが直接配信される
Next.js 15(2026年初頭現在の安定版)では、画像オプティマイザーはNode.js環境ではデフォルトでsharpを使う。Vercelでは、エッジベースの画像最適化サービスを使う。他のプラットフォームでは、設定に応じてsharpまたはsquooshにフォールバックする。
// 基本的な使用法 - ただし、これの背後で多くのことが起こっている
import Image from 'next/image';
export default function Hero() {
return (
<Image
src="/hero.jpg"
alt="Product hero shot"
width={1200}
height={630}
priority
quality={80}
/>
);
}
そのpriorityプロップは見た目以上のことをしている。HTMLにfetchpriority="high"を追加し、レイジーロードを無効にし、<head>に<link>プリロードタグを生成する。これがLCPに重要な理由については後で戻ってくる。
ほとんどの人が触らない設定
next.config.js(またはnext.config.tsに移行している場合)には、すべてを制御するimagesキーがある:
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 31536000, // 秒単位で1年
dangerouslyAllowSVG: false,
remotePatterns: [
{
protocol: 'https',
hostname: 'your-cms.com',
pathname: '/assets/**',
},
],
},
};
formats配列の順序が重要である。Next.jsはまずAVIFを試し、その次にWebPにフォールバックする。AVIFエンコーディングは遅いがより小さいファイルを生成する。このトレードオフを理解することは価値がある。
LCP問題: ヒーロー画像がスコアを台無しにしている理由
ほぼすべての監査で見かけるシナリオは: 美しいヒーロー画像があり、ファーストビューの上にあり、3秒以上かかって表示される。開発者はnext/imageを使い、完了したと思い、先に進んだ。しかし、スコアはひどい。
通常の犯人:
1. `priority`プロップが見つからない
デフォルトでは、next/imageはすべてをレイジーロードする。ファーストビューの下の画像には最適だが、LCP要素には致命的である。priorityがなければ、ブラウザは遅く画像を発見し、JavaScriptがハイドレートされた後、intersection observerが開始されている。
// ❌ これはLCP画像をレイジーロードする
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} />
// ✅ これはプリロードする
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} priority />
2. 低いクオリティ値での過度な圧縮
クオリティ値をquality={50}に設定して、より小さい = より速いと考えているチームを見ている。しかし、画像がぼやけて見えても、ChromeのLCPアルゴリズムはそれを完全にペイントするまで待つ必要がある。高DPIスクリーンでは、70未満のクオリティが目立つアーティファクトをしばしば引き起こし、デザインが安っぽく見える。
私の経験則: 写真は品質75-85、テキストまたはシャープなエッジを持つ画像は品質90以上。
3. `sizes`を正しく使用していない
sizes属性は、CSSが解析される前にブラウザがどの画像幅をリクエストするべきかを伝える。これがなければ、Next.jsはデフォルトで100vwを設定し、モバイルデバイスはデスクトップサイズの画像をダウンロードする。
<Image
src="/hero.jpg"
alt="Hero"
fill
priority
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
/>
このプロップ1つの変更で、最大の LCP 改善を得た。時には400-800msをモバイルで得ている。

フォーマット戦争: 2026年のAVIF対WebP対JPEG XL
フォーマットランドスケープはかなり定着している。現在の状況は以下の通り:
| フォーマット | ブラウザ対応(2026年) | 圧縮率 | エンコード速度 | 最適な用途 |
|---|---|---|---|---|
| AVIF | グローバル約95% | 優秀(WebPより30-50%小さい) | 遅い | 写真、ヒーロー画像 |
| WebP | グローバル約98% | 良好(JPEGより25-35%小さい) | 速い | 汎用 |
| JPEG XL | 約45%(Chromeは削除) | 優秀 | 中程度 | ウェブには推奨されない |
| JPEG | 普遍的 | ベースライン | 速い | フォールバックのみ |
| PNG | 普遍的 | 写真には不良 | 速い | 透過、スクリーンショット |
JPEG XLは有望な仕様を持っていたが、Chromeが2023年末にサポートを削除する決定は、実質的にウェブ使用を殺した。Safariはサポートを追加し、Firefoxは部分的なサポートがあるが、頼ることはできない。
私の推奨: formats: ['image/avif', 'image/webp']を設定して忘れる。Next.jsはAcceptヘッダーを通じてコンテンツネゴシエーションを自動的に処理する。
AVIFエンコーディングコスト
ここにドキュメントが強調しない何かがある: AVIFエンコーディングはCPU集約的である。Next.jsサーバーへの初回リクエスト時、1200pxのAVIF画像をエンコードするのに、適度なサーバーで2-5秒かかることがある。最初の訪問者がコストを払う。
この問題を軽減する戦略:
- ビルド時に事前生成する
next exportまたはカスタムビルドスクリプトを使用 - 組み込み画像最適化を持つCDNを使う (Cloudflare Images、Imgix、Cloudinary)
- キャッシュをウォームアップする デプロイ後、すべての重要な画像URLにヒットするスクリプトで
# シンプルなキャッシュウォームアップスクリプト
#!/bin/bash
URLs=("https://yoursite.com/_next/image?url=%2Fhero.jpg&w=1200&q=80"
"https://yoursite.com/_next/image?url=%2Fhero.jpg&w=750&q=80")
for url in "${URLs[@]}"; do
curl -s -o /dev/null -H "Accept: image/avif,image/webp" "$url"
echo "Warmed: $url"
done
レスポンシブ画像を正しく実装する
Next.jsのレスポンシブ画像は難しくないが、deviceSizes、imageSizes、sizesプロップがどのように連動するかを理解する必要がある。
`fill`レイアウトパターン
ビルド時にアスペクト比が分からない画像(CMSコンテンツ、ユーザーアップロード)については、fillプロップを使用する:
<div className="relative aspect-[16/9] w-full">
<Image
src={post.featuredImage}
alt={post.title}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
relativeポジショニングとアスペクト比を持つ親divが重要である。これなしでは、fill画像は高さが0に折りたたまれ、眉をひそめたくなるCLSスコアを得る。
``を使用したアート・ディレクション
時々、異なるスクリーンサイズで異なるトリミングが必要である。next/imageはネイティブに<picture>をサポートしていないが、回避策がある:
// アート・ディレクション回避策
export function ResponsiveHero({ mobileSrc, desktopSrc, alt }) {
return (
<>
<div className="block md:hidden relative aspect-[9/16] w-full">
<Image src={mobileSrc} alt={alt} fill priority sizes="100vw" />
</div>
<div className="hidden md:block relative aspect-[16/9] w-full">
<Image src={desktopSrc} alt={alt} fill priority sizes="100vw" />
</div>
</>
);
}
はい、このHTMLは両方の画像をダウンロードするが、1つだけレンダリングされ、非表示はpriorityを適用しないレイジーロードのおかげで読み込まれない(ビューポートに一致するものにのみ適用する)。
CDNとエッジ最適化戦略
Next.jsを自前でホストしている場合(多くのチームがしている),画像のCDN戦略が必要である。
オプション1: Vercelにやってもらう
Vercelの画像最適化はエッジで実行される。ほとんどのプロジェクトにおいて、これが最も簡単なパスである。2026年現在、Vercelのプロプランには最適化された5,000個のソース画像が含まれており、追加画像は1,000あたり5ドルである。エンタープライズプランはカスタム料金体系がある。
オプション2: 外部画像最適化サービス
CloudinaryとImgixとCloudflare Imagesはすべてloaderプロップまたはカスタムローダーを通じてNext.jsで動作する:
// next.config.js with Cloudinary
module.exports = {
images: {
loader: 'custom',
loaderFile: './lib/cloudinary-loader.js',
},
};
// lib/cloudinary-loader.js
export default function cloudinaryLoader({ src, width, quality }) {
const params = [
`w_${width}`,
`q_${quality || 'auto'}`,
'f_auto',
'c_limit',
];
return `https://res.cloudinary.com/your-cloud/image/upload/${params.join(',')}${src}`;
}
| サービス | 無料プラン | プロ価格(2026年) | エッジノード | AVIF対応 |
|---|---|---|---|---|
| Cloudinary | 25クレジット/月 | $89/月(25GB) | 60+ | はい |
| Imgix | なし | $100/月(100GB) | グローバル | はい |
| Cloudflare Images | なし | $5/月(100Kバリアント) | 310+ | はい |
| Vercel(組み込み) | 1,000枚(Hobby) | Proに含まれる | エッジ | はい |
ヘッドレスCMS開発プロジェクトの場合、通常はCloudinaryまたはCMSの組み込み画像パイプライン(Sanity、Contentful、Hygraphはすべてまともな画像APIを持っている)を使う。
オプション3: Cloudflare Polish + Next.js
すでにCloudflareの背後にいる場合、彼らのPolish機能はエッジでフォーマット変換を処理できる。Next.js画像最適化を無効にし、Cloudflareに作業させる:
module.exports = {
images: {
unoptimized: true, // Cloudflareに処理させる
},
};
このアプローチはそれほど好きではない。Next.jsが提供するレスポンシブサイジングを失うからだが、シンプルなセットアップでは機能する。
重要なものを測定する: ツールとベンチマーク
改善できないものは測定できない。ここが私のテストスタックである:
ラボツール
- Chrome DevTools Lighthouse(2026年v12): まだ出発点。シークレットモードで拡張なしで実行する。
- WebPageTest: Dulles, VAに設定、Moto G Powerで4G。これは現実的な「遅い」ユーザーを表す。
- Unlighthouse: サイト全体をバルク走査。忘れたページをキャッチするのに素晴らしい。
フィールドデータ
- Chrome UX Report(CrUX): Googleがランキング信号に使う実際のデータ。PageSpeed Insights と BigQuery で利用可能。
- web-vitals.js: アプリに追加して実際のユーザーメトリクスを収集:
// app/layout.tsx
import { onLCP, onINP, onCLS } from 'web-vitals';
if (typeof window !== 'undefined') {
onLCP(console.log);
onINP(console.log);
onCLS(console.log);
}
本番環境では、console.logの代わりに分析プラットフォームにこれらを送信する。Vercel Speed Insights と BigQuery に書き込むカスタムエンドポイントの組み合わせを使う。
2026年のベンチマークターゲット
今年監査したサイトに基づいて、画像が多いNext.jsサイトの「良好」は以下のようなものである:
- モバイルのLCP(p75): < 1.8秒(2.0秒閾値以下のバッファを提供)
- ファーストビュー上の合計画像重量: < 200KB
- ヒーロー画像読み込み時間: 4G上で< 800ms
- 画像からのCLS: 0
実際に成果を生む高度なテクニック
BlurHashを使用したぼかしプレースホルダー
Next.jsは静的インポートに対してネイティブにplaceholder="blur"をサポートしている。動的画像(CMSから)の場合、ぼかしデータURLを生成する必要がある:
import { getPlaiceholder } from 'plaiceholder';
export async function getStaticProps() {
const { base64 } = await getPlaiceholder('/path/to/image.jpg');
return {
props: { blurDataURL: base64 },
};
}
// コンポーネント内
<Image
src={dynamicUrl}
alt="Dynamic image"
fill
placeholder="blur"
blurDataURL={blurDataURL}
/>
これはLCPを直接改善しないが、認識されたパフォーマンスを劇的に改善し、CLSを防ぐ。
HTTP/3と早期ヒント
CDNがHTTP/3をサポートしている場合(Cloudflare、Fastly、Vercelはすべてサポート),103 Early Hintsを使用してHTMLドキュメントが完全に生成される前にLCP画像を送信し始めることができる:
// middleware.ts
import { NextResponse } from 'next/server';
export function middleware(request) {
const response = NextResponse.next();
if (request.nextUrl.pathname === '/') {
response.headers.set(
'Link',
'</hero.avif>; rel=preload; as=image; type="image/avif"'
);
}
return response;
}
CSS `content-visibility`を使用したスケルトン読み込み
多くの画像を持つ長いページの場合、content-visibility: autoはブラウザに画面外のコンテンツのレンダリングを完全にスキップするよう伝える:
.image-grid-item {
content-visibility: auto;
contain-intrinsic-size: 300px 200px; /* 推定サイズ */
}
これにより、今年の第4四半期に最適化した製品リストページでINPが30-40ms削減された。
すべての監査で見かける一般的な間違い
装飾的なSVGに
next/imageを使う: 単に<img>タグを使うか、SVGをインラインにする。最適化パイプラインはゼロの利益のためにオーバーヘッドを追加する。「画像がぼやけているから」グローバルに
unoptimizedを設定する: 代わりにクオリティ設定を修正する。unoptimizedはすべてをバイパスする。altテキストを設定するのを忘れる: これはアクセシビリティに限らない。Googleの画像検索はトラフィックを生み、インデックス化するにはaltテキストが必要である。minimumCacheTTLを設定しない: デフォルトは60秒である。つまり、負荷の下でサーバーが毎分同じ画像を再最適化する。最低でも2592000(30日)に設定する。巨大なソース画像を使用する: 6000x4000pxのDSLR写真をアップロードし、Next.jsにそれを処理することを期待する。ソース画像を最大表示サイズの2倍に前処理する。
ネットワークタブを無視する: DevTools を開き、
Imgでフィルタリング、サイズでソート。30秒でこれらの問題を見つける。
本番サイトでこれらの問題に苦しんでいる場合、それは私たちが解決するタイプの問題である。料金を確認するか、直接連絡する。パフォーマンス監査はスタンドアロンエンゲージメントとして実施する。
FAQ
next/imageは自動的に画像をAVIFに変換するのか?
はい。next.config.jsのimages.formats配列に'image/avif'がある場合(Next.js 14以降のデフォルトに含まれている)。変換は、ブラウザがimage/avifを含むAcceptヘッダーを送信するときにオンデマンドで発生する。最初のリクエストはエンコーディングのため遅いが、その後のリクエストはキャッシュから配信される。
AVIFは実際にWebPと比較して画像ファイルサイズをどの程度削減するのか?
数百の本番画像全体のテストでは、AVIFは同等のビジュアル品質でWebPより平均30-50%小さく、JPEGより50-70%小さい。利益は写真コンテンツで最も劇的である。スクリーンショットまたはテキスト付き画像の場合、差は15-25%に狭まる。
複数の画像でpriorityを使用するべきか?
控えめに使う。実際にファーストビューの上にあり、初回読み込みで表示される画像にのみ使う。2-3個以上の画像にpriorityを追加すると、ブラウザはすべてを同時に優先化できないため、目的が無くなる。ホームページのヒーローとロゴ。それだけである。
LCP はなぜ next/image と priority を使用してもまだ遅いのか?
最も一般的な理由はサーバー応答時間(TTFB)がバジェットを消費していることである。Next.jsサーバーが800msで応答する場合、画像の読み込みとペイントに残されたのは1.2秒だけである。他の犯人: レンダリング・ブロック CSS、ハイドレーションを遅延させる大きなJavaScriptバンドル、または画像ソースが遅いオリジンサーバーにある。
静的エクスポート(next export)で next/image を使用できるか?
組み込み最適化では使用できない。静的エクスポートにはimages.unoptimized: trueまたはCloudinaryやImgixなどの外部サービスを指すカスタムローダーが必要である。これが純粋に静的なサイトにAstroを時々推奨する理由である。その画像処理は実行中のサーバーを必要としない。
ヘッドレスCMSの next/image を使用する画像をどのように処理するか?
next.config.jsのimages.remotePatternsにCMSの画像ドメインを追加する。ほとんどのヘッドレスCMSプラットフォーム(Sanity、Contentful、Storyblok、Hygraph)には独自の画像変換APIがある。それらをカスタムローダー経由で使用するか、Next.js に最適化を処理させることができる。ヘッドレスCMSプロジェクトではCMSのネイティブパイプラインを好む。サーバー負荷を削減するからである。
画像最適化が Core Web Vitals ランキング信号に与える影響は何か?
Googleは2025年にCore Web Vitalsがランキング信号であることを確認したが、コンテンツ関連性が依然として支配的である。つまり、トップ結果全体でコンテンツ品質が類似した競争的なクエリの場合、CWVがタイブレーカーになる可能性がある。主に最適化されていない画像が原因だったLCP問題を修正した後、3-8ポジション移動したサイトを見ている。
ファーストビュー下のすべての画像をレイジーロードすべきか?
はい。Next.jsはデフォルトでこれを行う(priorityを追加しない限り)。ネイティブloading="lazy"属性はnext/imageが内部で使用するものである。JavaScriptベースのレイジーロードライブラリはもう必要ない。ブラウザネイティブのレイジーロードは2022年から全主要ブラウザ全体で安定している。