画像は、Webページで最も重く・最も LCP に効く要素です。最適化すれば Core Web Vitals が上がり、SEO と離脱率が改善します。一方、使い方を誤ると変換課金で請求が跳ねます。この2つを両立させるのが Vercel の画像最適化の勘所です。
この記事は Vercel Image Optimization の公式仕様に忠実に、next/image の使い方とコスト最適化をまとめます。全体像は Vercel 本番運用ガイド、コストは Active CPU 最適化 を参照してください。
仕組み:動的変換 → CDN キャッシュ
next/image(Astro/Nuxt も同等コンポーネント)を使うと、Vercel が元画像を動的に最適化します。
img素のタグを使うと最適化はバイパスされ、元画像がそのまま配信される。Imageコンポーネントを使うと、Vercel の最適化パイプラインに乗る——AVIF/WebP への変換、デバイス幅に合わせたリサイズ、そして CDN キャッシュ。- キャッシュ状態:
- HIT:キャッシュから配信(変換なし)
- MISS:変換 → キャッシュ → 配信(transformation + cache write 課金)
- STALE:キャッシュ配信しつつ裏で再変換(同上)
// app/page.tsx — next/image の基本
import Image from "next/image";
import hero from "@/public/hero.jpg"; // ローカル画像(ビルド時に解析)
export default function Page() {
return (
<Image
src={hero}
alt="製品のヒーロー画像" // a11y:意味のある alt を必ず
priority // LCP 画像は priority で先読み
sizes="(max-width: 768px) 100vw, 50vw" // レスポンシブの幅指定
/>
);
}
a11y の必須事項:
altは飾りではありません。意味のある画像には内容を説明するalt、装飾画像にはalt=""を。スクリーンリーダー利用者の体験と、画像 SEO の両方に効きます(Web アクセシビリティ)。
設定:remotePatterns / localPatterns で許可を絞る
どの画像ソースを最適化してよいかを next.config.ts で明示します。無制限に許可しないのがセキュリティとコストの両面で重要です。
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
// ローカル(public 配下)
localPatterns: [{ pathname: "/assets/images/**", search: "" }],
// リモート(外部ホスト)
remotePatterns: [
{
protocol: "https",
hostname: "cdn.example.com",
// 自分が所有しないホストは、乱用防止にアカウントID等を含める
pathname: "/account123/**",
search: "",
},
],
// 変換のバリエーションを絞る=キャッシュ効率とコストに効く
formats: ["image/avif", "image/webp"],
qualities: [75], // 品質を1つに固定するとキャッシュキーが減る
},
};
export default nextConfig;
乱用防止:所有していない
hostnameを許可するときは、pathnameにアカウント ID 等を含めて自分のソースだけに限定します。ワイルドカードを広げすぎると、第三者経由の変換で課金を膨らまされるリスクがあります。
キャッシュキーと保持期間
最適化画像は CDN にキャッシュされ、キャッシュキーが同じなら変換は再実行されません(=課金されない)。キーは:
- Project ID
q(品質 1〜100)w(幅 px)url(ローカルはコンテンツハッシュ、リモートは絶対URL)Acceptヘッダ(正規化)
保持期間:
| 種類 | 保持 |
|---|---|
| ローカル画像 | CDN で最大31日 |
| リモート画像 | 上流の Cache-Control max-age か minimumCacheTTL(既定 3600秒)の大きい方 |
再デプロイではキャッシュは無効化されません。ローカル画像は「同名で中身を差し替えて再デプロイ」か、手動/プログラムでのpurgeで無効化。リモート画像は一度キャッシュされると、期限切れか purge まで古い版が出続けます。「画像を差し替えたのに古いまま」はこれが原因。
変換 URL の形式
Image コンポーネントは src を最適化 URL に置換します。
- Next.js:
/_next/image?url={src}&w=3840&q=75 - Nuxt/Astro 等:
/_vercel/image?url={src}&w=3840&q=75
コスト最適化:請求を跳ねさせない
画像最適化は「請求が増える主因」の常連です。効く順に。
① 最適化すべきでない画像を最適化しない
以下は unoptimized で素通しし、変換クォータを使いません。
- 10KB 未満のアイコン/サムネイル(既に小さい)
- GIF 等のアニメ画像
- SVG(ベクター。最適化対象外)
- 頻繁に変わる画像(キャッシュが効かず変換が走り続ける)
// 小さいアイコンや SVG は最適化しない
<Image src="/icon.svg" alt="" width={24} height={24} unoptimized />
② バリエーションを絞る
キャッシュキーは q・w・Accept の組み合わせで増えます。qualities を1つ(例 75)に固定し、sizes/deviceSizes を必要な幅だけに絞ると、ユニークな変換数=課金が減り、HIT 率が上がります。
③ キャッシュを効かせる
- リモート画像は
minimumCacheTTLを伸ばして再変換を減らす(更新頻度とのトレードオフ)。 - 変換結果はデプロイ跨ぎで持続するので、不要な purge をしない。
④ 何を消費しているか見る
Observability の Image Optimization Insights で、変換数・cache read/write・Fast Data Transfer を確認し、重い箇所を特定します(可観測性)。
いつ使う/使わない
| 最適化すべき | 最適化不要 |
|---|---|
| 製品写真・ヒーロー画像(大きい・高品質) | 10KB 未満のアイコン |
| ユーザーアップロード画像 | アニメ GIF |
| レスポンシブで幅が変わる画像 | SVG(ベクター) |
| 写真ポートフォリオ等、画像が主役 | 頻繁に変わる画像 |
ユーザーアップロード画像は、保存を Vercel Blob(client upload)にし、表示を
next/imageのremotePatternsで最適化、という組み合わせが定番です。
本番チェックリスト(画像最適化)
- 写真/ヒーロー/アップロード画像は
next/imageで最適化 -
altを意味に応じて設定(a11y・画像SEO) - LCP 画像に
priority、sizesでレスポンシブ - 小アイコン/SVG/GIF/頻繁更新は
unoptimized -
remotePatterns/localPatternsでソースを限定、外部は pathname を絞る -
qualities・幅のバリエーションを絞る(HIT 率↑・課金↓) - 画像差し替え時はキャッシュ無効化(同名差し替え or purge)を理解
- Observability で変換数・転送量を監視
まとめ
画像最適化は「速さ(CWV・SEO)」と「コスト」を同時に作る領域です。
next/imageで AVIF/WebP 変換・レスポンシブ・CDN キャッシュ- キャッシュキー(
q/w/url/Accept)と保持期間を理解 - コストは ①不要画像を最適化しない ②バリエーションを絞る ③キャッシュを効かせる
- ソースは
remotePatternsで限定、再デプロイでキャッシュは消えない - Observability で消費を監視し、計測 → 最適化
CWV を上げつつ画像コストを抑えるチューニングを、案件として承ります。本クラスタの起点は Vercel 本番運用ガイド です。
本記事は Vercel Image Optimization 公式ドキュメント(2026年6月時点)に基づきます。仕様・課金・上限は更新されるため、本番採用時は公式で最新値を確認してください。