JA EN

画像キャッシュ戦略の完全ガイド - Cache-Control, ETag, CDN の最適設定

· 約 9 分で読めます

Web 画像キャッシュの基本 - ブラウザキャッシュと CDN キャッシュの役割

画像キャッシュは Web パフォーマンスの要です。適切なキャッシュ戦略により、画像の再ダウンロードを防ぎ、ページ読み込み時間を劇的に短縮できます。キャッシュは大きく 2 層に分かれます。

ブラウザキャッシュ (クライアントサイド): ユーザーのデバイスに画像を保存し、同じ画像への再リクエストを完全に排除します。HTTP レスポンスヘッダーの Cache-Control で制御され、キャッシュヒット時はネットワークリクエストが発生しないため、表示速度は事実上ゼロ秒です。

CDN キャッシュ (エッジサーバー): オリジンサーバーの前段に配置されたエッジサーバーに画像をキャッシュします。ブラウザキャッシュがない場合でも、地理的に近いエッジサーバーから配信することでレイテンシを削減します。CloudFront、Cloudflare、Fastly などが代表的な CDN です。

キャッシュの効果: HTTP Archive の調査によると、適切なキャッシュ設定により画像リクエストの 60-80% がキャッシュから提供されます。これは帯域幅コストの削減とサーバー負荷の軽減にも直結します。特に画像は Web ページの転送量の約 50% を占めるため、キャッシュの効果が最も大きいリソースタイプです。

キャッシュ戦略の設計では、「キャッシュの鮮度 (freshness)」と「キャッシュの無効化 (invalidation)」のバランスが重要です。長すぎるキャッシュは古い画像が表示されるリスクを生み、短すぎるキャッシュはパフォーマンスの恩恵を失います。

Cache-Control ヘッダーの設計 - ディレクティブの組み合わせ方

Cache-Control は HTTP キャッシュの動作を制御する最も重要なヘッダーです。画像の種類と更新頻度に応じて、適切なディレクティブを組み合わせます。

不変の静的画像 (ハッシュ付きファイル名):

Cache-Control: public, max-age=31536000, immutable

ファイル名にコンテンツハッシュを含む画像 (例: hero-a1b2c3d4.jpg) は、内容が変わればファイル名も変わるため、1 年間 (31536000 秒) のキャッシュを安全に設定できます。immutable ディレクティブは、ブラウザがキャッシュの再検証 (conditional request) すら行わないことを示します。

更新される可能性がある画像:

Cache-Control: public, max-age=86400, must-revalidate

ユーザーアップロード画像やプロフィール画像など、同じ URL で内容が変わる可能性がある画像には、短めの max-age (1 日 = 86400 秒) と must-revalidate を設定します。キャッシュ期限切れ後は必ずサーバーに再検証を行います。

キャッシュ禁止:

Cache-Control: no-store

個人情報を含む画像 (本人確認書類など) はキャッシュしてはいけません。no-store はブラウザと中間キャッシュの両方でキャッシュを完全に禁止します。

stale-while-revalidate:

Cache-Control: public, max-age=3600, stale-while-revalidate=86400

キャッシュ期限切れ後も古いキャッシュを即座に返しつつ、バックグラウンドで再検証を行うディレクティブです。ユーザーは常に即座にレスポンスを受け取れるため、知覚速度が向上します。

ETag と条件付きリクエスト - 効率的なキャッシュ再検証

ETag (Entity Tag) は、リソースの特定バージョンを識別する文字列です。キャッシュの有効期限が切れた後、リソースが実際に変更されたかどうかを効率的に確認するために使用されます。

ETag の動作フロー:

304 Not Modified レスポンスはボディを含まないため、画像データの再転送を回避できます。1MB の画像でも、変更がなければ数百バイトの 304 レスポンスで済みます。

ETag の生成方法:

Last-Modified との比較: Last-Modified ヘッダーも条件付きリクエスト (If-Modified-Since) に使用できますが、秒単位の精度しかなく、ファイルシステムのタイムスタンプに依存するため信頼性が低い場合があります。ETag はコンテンツベースの検証であり、より正確です。CDN 環境では ETag の使用を推奨します。

注意点: 複数のオリジンサーバーがある場合、同じファイルに対して異なる ETag が生成されないよう注意が必要です。inode ベースの ETag (Apache のデフォルト) はサーバーごとに異なるため、コンテンツハッシュベースに変更してください。

CDN キャッシュの設計 - CloudFront と Cloudflare の設定例

CDN のキャッシュ設定は、オリジンサーバーの Cache-Control ヘッダーを尊重する場合と、CDN 側で独自のキャッシュポリシーを設定する場合があります。

CloudFront の設定:

Cloudflare の設定:

キャッシュキーの設計: CDN のキャッシュキーには URL パスに加えて、画像フォーマットのネゴシエーションに使用する Accept ヘッダーを含める必要があります。これにより、同じ URL でも WebP 対応ブラウザには WebP を、非対応ブラウザには JPEG をキャッシュから返せます。Vary ヘッダーに Accept を含めることで実現します。

キャッシュ無効化戦略 - 画像更新時の確実な反映方法

キャッシュの最大の課題は「古いキャッシュをいかに確実に無効化するか」です。画像を更新しても、ユーザーのブラウザや CDN に古いバージョンが残っていると、更新が反映されません。

戦略 1: コンテンツハッシュによるファイル名バージョニング

最も確実な方法です。画像ファイル名にコンテンツのハッシュ値を含めます。

hero-image-a1b2c3d4e5f6.jpg

画像が更新されるとハッシュが変わり、新しい URL になるため、古いキャッシュの問題が完全に解消されます。HTML 側の参照も同時に更新する必要があるため、ビルドパイプラインとの統合が前提です。Webpack の [contenthash] や Vite のアセットハッシュ機能で自動化できます。

戦略 2: クエリ文字列によるバージョニング

hero-image.jpg?v=20250723

ファイル名を変えずにクエリ文字列でバージョンを管理する方法です。実装が簡単ですが、一部の CDN やプロキシがクエリ文字列を無視してキャッシュする場合があるため、確実性はハッシュ方式に劣ります。

戦略 3: CDN のキャッシュパージ (Invalidation)

CDN のエッジキャッシュを強制的に削除する方法です。CloudFront では CreateInvalidation API、Cloudflare では Purge Cache API で実行できます。即座に反映されますが、エッジロケーションが多い場合は全拠点への伝播に数分かかることがあります。

推奨アプローチ: コンテンツハッシュによるファイル名バージョニングを基本とし、緊急時のみ CDN パージを併用する構成が最も堅牢です。ユーザーアップロード画像など、URL が固定される場合は短い max-age + ETag の組み合わせで対応します。

Service Worker による高度なキャッシュ制御 - オフライン対応と戦略的キャッシュ

Service Worker を使うと、ブラウザの標準キャッシュメカニズムを超えた高度なキャッシュ戦略を実装できます。画像のオフライン対応や、ネットワーク状況に応じた適応的な配信が可能になります。

Cache First 戦略 (画像に最適):

self.addEventListener("fetch", (event) => {
if (event.request.destination === "image") {
event.respondWith(
caches.match(event.request).then((cached) => {
return cached || fetch(event.request).then((response) => {
const cache = await caches.open("images-v1");
cache.put(event.request, response.clone());
return response;
});
})
);
}
});

この戦略では、キャッシュにヒットすれば即座に返し、ミスした場合のみネットワークリクエストを行います。画像は頻繁に変更されないため、Cache First が最適です。

Stale While Revalidate 戦略: キャッシュから即座に返しつつ、バックグラウンドで最新版を取得してキャッシュを更新します。次回アクセス時には最新版が表示されます。プロフィール画像など、更新頻度が中程度の画像に適しています。

キャッシュサイズの管理: Service Worker のキャッシュストレージには容量制限があります (ブラウザにより異なるが、通常 50MB-数百 MB)。古いエントリを LRU (Least Recently Used) で自動削除するロジックを実装してください。Workbox ライブラリの ExpirationPlugin を使えば、最大エントリ数や最大保存期間を簡単に設定できます。

レスポンシブ画像のキャッシュ: srcset で複数サイズの画像を提供する場合、Service Worker でデバイスの画面幅に応じた最適なサイズのみをキャッシュすることで、ストレージ使用量を削減できます。不要な高解像度画像のキャッシュを避け、ユーザーのデバイスに適したサイズだけを保持する設計が効率的です。

関連記事

画像 CDN の設定と最適化 - CloudFront, Cloudflare で実現する高速配信

画像 CDN の仕組みと設定方法を解説。CloudFront や Cloudflare を使った画像の高速配信、動的リサイズ、フォーマット変換、キャッシュ戦略を実践的に紹介します。

大規模サイトの画像配信アーキテクチャ - 設計パターンと実装

月間数億 PV 規模のサイトで求められる画像配信アーキテクチャを解説。CDN 設計、オリジン構成、動的変換、キャッシュ戦略の実践的なパターンを紹介します。

画像変換 API の設計パターン - URL ベース、リクエストボディ、非同期処理の比較

画像変換 API を設計する際のアーキテクチャパターンを解説。URL パラメータ方式、REST API 方式、非同期キュー方式の特性を比較し、スケーラブルな設計指針を提示します。

コンテントネゴシエーションで最適な画像を配信 - Accept ヘッダーと CDN の連携

HTTP コンテントネゴシエーションを活用し、ブラウザの対応フォーマットに応じて WebP や AVIF を自動配信する仕組みを解説。CDN 設定と Vary ヘッダーの正しい運用方法を紹介します。

Web 用画像のファイルサイズ最適化戦略 - 品質を保ちながら軽量化する技術

Web パフォーマンスを最大化するための画像ファイルサイズ最適化手法を、フォーマット選択からメタデータ除去まで体系的に解説します。

Web 画像最適化チェックリスト - 実務で使える 15 項目を徹底解説

Web サイトの画像最適化に必要な 15 のチェック項目を実務視点で解説。Core Web Vitals 改善に直結する具体的な施策と優先順位を紹介します。

関連用語