Webコンテンツ表示不能を引き起こす「resource was not cached」エラーの深層と究極の対策ガイド
はじめに:なぜWebサイトはキャッシュを使うのか?
インターネットを利用しているとき、Webサイトの表示が遅いと感じた経験は誰にでもあるでしょう。Webサイトの表示速度は、ユーザー体験に直結する重要な要素です。速く快適なWebサイトはユーザーの満足度を高め、検索エンジンでの評価(SEO)にも好影響を与えます。この表示速度を劇的に向上させる技術の一つが「Webキャッシュ」です。
Webキャッシュとは、Webブラウザやプロキシサーバーなどが、一度ダウンロードしたWebサイトのリソース(HTMLファイル、CSSファイル、JavaScriptファイル、画像、動画など)を一時的に保存しておく仕組みのことです。次に同じリソースが必要になったとき、ネットワーク経由で再度ダウンロードする代わりに、手元のキャッシュから読み込むことで、高速に表示することができます。
例えば、あなたが頻繁に訪れるニュースサイトがあるとします。サイトのデザインを決めているCSSファイルやロゴ画像は、頻繁に変わるものではありません。初回訪問時にこれらのリソースがキャッシュに保存されていれば、2回目以降の訪問ではサーバーからダウンロードする必要がなくなり、ページの表示速度が大幅に向上します。これは、ユーザーにとっても快適であり、Webサイト運営者にとってもサーバーへの負荷軽減や帯域幅の節約につながるメリットがあります。
しかし、このキャッシュ機構は常にうまく機能するとは限りません。予期せぬ理由によりキャッシュが利用されず、Webコンテンツが正しく表示されなかったり、表示に時間がかかったりする問題が発生することがあります。その際、開発者ツールなどで確認できるエラーメッセージの一つに、「resource was not cached」という状況を示すものがあります。(正確なエラーメッセージの形式はブラウザやツールによって異なりますが、概念としては「リソースがキャッシュから読み込まれなかった」「キャッシュが無効になった」といった状態を指します。)
本記事では、この「resource was not cached」という状況がなぜ発生するのか、その原因を深掘りし、ブラウザ側、サーバー側、ネットワーク側など、様々な側面から考えられる詳細な対策方法を、約5000語にわたって徹底的に解説します。Webサイトの開発者、運用担当者、あるいはこの問題に直面しているユーザーにとって、包括的な理解と解決策を提供することを目指します。
第1章 Webキャッシュの基礎:どのように機能するのか?
「resource was not cached」という問題を理解するためには、まずWebキャッシュがどのように機能するかを知る必要があります。Webキャッシュは主に以下のレベルで機能します。
- ブラウザキャッシュ (Browser Cache): 最も身近なキャッシュです。ユーザーのWebブラウザ(Chrome, Firefox, Safari, Edgeなど)が、訪問したWebサイトのリソースをローカルコンピューターに保存します。
- プロキシキャッシュ (Proxy Cache): ネットワーク内のプロキシサーバー(企業内のゲートウェイやインターネットサービスプロバイダ(ISP)のサーバーなど)が、複数のユーザーからのリクエストに対してリソースをキャッシュします。これにより、同じリソースへのリクエストが複数あっても、一度のダウンロードで済み、ネットワーク全体の負荷を軽減します。
- サーバーサイドキャッシュ (Server-Side Cache): Webサーバー自身や、その手前に配置されるリバースプロキシ、CDN (Content Delivery Network)などがコンテンツをキャッシュします。データベースの結果、生成されたHTML、静的ファイルなどが対象となります。これは、オリジンサーバー(コンテンツの元となるサーバー)への負荷を減らす役割があります。
これらのキャッシュは、HTTPヘッダーと呼ばれる情報交換メカニズムを通じて連携します。クライアント(ブラウザなど)からのリクエストと、サーバーからのレスポンスには、キャッシュの振る舞いを制御するための特別なヘッダーが含まれています。主なHTTPキャッシュ関連ヘッダーには以下のものがあります。
Cache-Control
: キャッシュの有効期限や振る舞いを指定する最も強力で新しいヘッダーです。max-age
(秒単位の有効期限)、no-cache
(キャッシュしても良いが利用前にサーバーへの確認が必要)、no-store
(キャッシュしてはいけない)、public
(プロキシなどもキャッシュ可能)、private
(ブラウザのみキャッシュ可能)、must-revalidate
(有効期限切れ後は必ずサーバーへ確認が必要) などのディレクティブがあります。Expires
: 古いヘッダーですが、特定の日時を絶対的な有効期限として指定します。Cache-Control
のmax-age
が優先されます。Pragma
: HTTP/1.0のヘッダーで、主に後方互換性のために使用されます。Pragma: no-cache
は、リクエストに対してキャッシュを使用しないように指示することがありますが、Cache-Control
の方が優先されます。ETag
(Entity Tag): リソースの特定のバージョンを示す識別子です。リソースの内容が変更されるとETag
も変わります。ブラウザはキャッシュされたリソースとともにこのETag
を保存し、次に同じリソースが必要になったときにIf-None-Match
ヘッダーでサーバーに送信します。サーバーは現在のリソースのETag
と比較し、一致すればコンテンツを送信せず304 Not Modifiedステータスコードを返します。Last-Modified
: リソースが最後に更新された日時を示します。ブラウザはキャッシュされたリソースとともにこの日時を保存し、次に同じリソースが必要になったときにIf-Modified-Since
ヘッダーでサーバーに送信します。サーバーはリソースの最終更新日時と比較し、If-Modified-Since
以降に変更がなければコンテンツを送信せず304 Not Modifiedを返します。
ブラウザがリソースをリクエストする際のキャッシュの基本的な流れは以下のようになります。
- ブラウザは目的のリソースのURLを確認します。
- ブラウザキャッシュにそのURLに対応するリソースが保存されているか確認します。
- 保存されている場合、キャッシュされたリソースの有効期限(
Cache-Control: max-age
やExpires
で指定された期間)を確認します。 - 有効期限内の場合、ブラウザはネットワークアクセスを行わず、キャッシュからリソースを即座に読み込みます。これが最も高速なケースです。
- 有効期限が切れている、あるいは
Cache-Control: no-cache
やmust-revalidate
が指定されている場合、ブラウザはサーバーに対してリソースの更新を確認するリクエストを送信します。このリクエストには、キャッシュされたリソースのETag
(If-None-Match
ヘッダーとして) やLast-Modified
日時 (If-Modified-Since
ヘッダーとして) が含まれます。 - サーバーはこれらのヘッダーを受け取り、リソースがブラウザのキャッシュ以降に変更されていないかを判断します。
- 変更がない場合、サーバーはコンテンツ本体を送信せず、
304 Not Modified
というステータスコードを返します。ブラウザはこのレスポンスを受け取り、キャッシュされたリソースがまだ有効であることを認識し、キャッシュから読み込みます。これも高速なケースです。 - 変更がある場合、サーバーは新しいリソースの内容ととも
に200 OK
というステータスコードを返します。ブラウザは新しいリソースをダウンロードし、キャッシュを更新します。
- 変更がない場合、サーバーはコンテンツ本体を送信せず、
- ブラウザキャッシュにリソースが保存されていない場合、ブラウザはサーバーにリソースを要求する通常の
200 OK
リクエストを送信します。サーバーはリソースを返送し、ブラウザはそれを表示するとともに、レスポンスヘッダーに従ってキャッシュに保存します。
第2章 「resource was not cached」とは具体的に何を意味するのか?
「resource was not cached」という状況は、文字通り「リソースがキャッシュから読み込まれなかった」ことを意味します。これは、先ほどのキャッシュ利用フローの「4. 有効期限内の場合、キャッシュから即座に読み込む」という状態にならなかった、または「6. 変更がない場合、304 Not Modifiedを受け取りキャッシュから読み込む」という状態にならなかったことを指します。
つまり、以下のいずれかの理由で、ブラウザがキャッシュを使わず、ネットワーク経由でリソースを再ダウンロードした、あるいはダウンロードを試みたが失敗した状況を示唆しています。
- キャッシュが存在しない: 初回アクセス、またはブラウザキャッシュがクリアされた後。
- キャッシュが存在するが無効と判断された:
- 有効期限が切れており、かつサーバーへの再検証 (
If-None-Match
,If-Modified-Since
) が失敗したか、サーバーが変更ありと判断した(200 OK
レスポンス)。 Cache-Control: no-cache
が指定されており、サーバーへの再検証が失敗したか、サーバーが変更ありと判断した(200 OK
レスポンス)。Cache-Control: no-store
が指定されており、そもそもキャッシュ自体が禁止されている。- リクエストがキャッシュを使用しない設定で行われた(例: 強制リロード、開発者ツールでの設定)。
- ブラウザキャッシュ自体が破損している、または正常に機能していない。
- 有効期限が切れており、かつサーバーへの再検証 (
- Service Workerなど、ブラウザキャッシュ以外のキャッシュ機構がリソースを提供できなかった。
- 何らかの理由で、キャッシュ検証リクエスト(
If-None-Match
,If-Modified-Since
)がサーバーに到達しなかった、あるいはサーバーからの応答が正しく処理されなかった。
開発者ツールのネットワークタブでリソースを確認すると、「Size」カラムに「from disk cache」や「from memory cache」と表示される場合は、キャッシュから読み込まれています。304 Not Modified
のレスポンスコードでサイズが小さく表示される場合も、キャッシュが検証後に利用されています。しかし、「resource was not cached」と表示される状況(または、サイズカラムにリソースのバイトサイズが表示され、ステータスコードが200 OK
となっている場合)は、キャッシュを使わずにネットワークからリソースを取得したことを示しています。
この「ネットワークからの取得」が問題なく完了すれば、単に表示速度が遅くなるだけで済みます。しかし、ネットワークエラー、サーバーエラー、あるいはその他の問題が同時に発生している場合、リソースのダウンロード自体が失敗し、結果としてWebコンテンツの表示が崩れたり、完全に表示不能になったりするのです。
したがって、「resource was not cached」という状況は、単にキャッシュが使われなかった事実を示すだけでなく、その背後にあるキャッシュが使われなかった理由、そしてその結果発生したダウンロードや表示の失敗こそが、ユーザーが直面する表示不能問題の根本原因となることが多いのです。
第3章 「resource was not cached」の主な原因と対策
ここからは、「resource was not cached」という状況を引き起こす具体的な原因を探り、それぞれに対する詳細な対策方法を解説します。原因はクライアント側、サーバー側、ネットワーク側、アプリケーション側など多岐にわたります。
3.1 クライアント側の原因と対策 (ブラウザ・ユーザー側)
最もシンプルでユーザー自身が試せる対策は、ブラウザ側に起因する問題を解消することです。
原因 3.1.1 ブラウザキャッシュの破損または不整合
ブラウザに保存されているキャッシュデータが何らかの理由で破損している、あるいは古い情報と新しい情報の間で不整合が起きている可能性があります。これにより、ブラウザがキャッシュを正しく利用できなくなることがあります。
対策 3.1.1: ブラウザキャッシュのクリア
最も一般的な対策です。ブラウザに保存されているキャッシュされたリソースを全て削除することで、次回アクセス時には必ずサーバーから最新のリソースを取得し直すことになります。
- 手順 (主要ブラウザ):
- Google Chrome: 設定 > プライバシーとセキュリティ > 閲覧履歴データの削除 > 「キャッシュされた画像とファイル」にチェックを入れて期間を選択(「全期間」を推奨)> 「データを削除」。
- Mozilla Firefox: オプション > プライバシーとセキュリティ > 「履歴」セクションの「履歴を消去」 > 「キャッシュ」にチェックを入れて期間を選択(「すべての履歴」を推奨)> 「OK」。
- Microsoft Edge: 設定 > プライバシー、検索、サービス > 「閲覧データをクリア」セクションの「クリアするデータの選択」 > 「キャッシュされた画像とファイル」にチェックを入れて期間を選択(「すべての期間」を推奨)> 「今すぐクリア」。
- Safari (macOS): Safari > 環境設定 > 詳細タブ > メニューバーに「開発」メニューを表示にチェック > 開発メニュー > キャッシュを空にする。
キャッシュをクリアした後、再度問題のWebサイトにアクセスしてみてください。これで問題が解決することがよくあります。
原因 3.1.2 強制リロード (Hard Refresh) の実行
ユーザーが意図的に、あるいは無意識に強制リロードを実行した場合、ブラウザはキャッシュを無視してサーバーから最新のリソースを取得しようとします。開発者ツールを開いている状態でリロードした場合も、デフォルト設定によってはキャッシュが無効化されることがあります。
- 強制リロードのキーボードショートカット:
- Windows/Linux:
Ctrl + F5
またはShift + F5
またはCtrl + Shift + R
- macOS:
Cmd + Shift + R
- Windows/Linux:
強制リロードは、開発者が最新の変更を確認するためによく行う操作ですが、ユーザーが誤って行った場合や、前回のアクセス時に強制リロードされた結果キャッシュが構築されず、次のアクセスでもキャッシュが利用できなかった、という状況も考えられます。
対策 3.1.2: 通常のリロードとキャッシュクリアの組み合わせ
強制リロードは一時的にキャッシュを無視する操作です。普段のアクセスでは通常のキャッシュが利用されるように、一度キャッシュをクリアし、その後通常のリロード (F5
または Cmd + R
) を行って、キャッシュが正しく構築されるか確認してください。開発者ツールが開いている場合は、キャッシュを無効化する設定になっていないかも確認します(ネットワークタブの設定など)。
原因 3.1.3 シークレットモード/プライベートブラウジングの利用
シークレットモードやプライベートブラウジングは、セッション終了時に履歴、Cookie、サイトデータ(キャッシュも含む)を保持しないように設計されています。これらのモードでアクセスした場合、過去のキャッシュは利用されず、セッション中もキャッシュは保持されないか、一時的なものとなります。
対策 3.1.3: 通常モードでのアクセスを試す
シークレットモードやプライベートブラウジングで問題が発生している場合、通常モードでアクセスしてみてください。通常モードであれば、ブラウザキャッシュが利用される可能性があります。もし通常モードで問題が発生しないのであれば、原因はモードの特性によるものと考えられます。
原因 3.1.4 ブラウザ拡張機能/アドオンの干渉
一部のブラウザ拡張機能やアドオン(例: 広告ブロッカー、セキュリティ関連拡張機能、開発者向けツール)が、Webサイトのリソース読み込みやキャッシュ機構に干渉し、正常なキャッシュ利用を妨げることがあります。
対策 3.1.4: 拡張機能/アドオンの一時的な無効化
インストール済みのブラウザ拡張機能を一つずつ、または全て一時的に無効化して、問題が解決するか確認します。
- 手順: ブラウザの設定メニューから拡張機能/アドオン管理画面を開き、怪しいものや最近インストールしたものを無効化してみてください。
拡張機能が無効化された状態で問題が解決する場合、その拡張機能が原因である可能性が高いです。どの拡張機能が原因かを特定するには、一つずつ有効化しながら確認する必要があります。
原因 3.1.5 古いブラウザバージョン
使用しているブラウザのバージョンが古すぎる場合、最新のHTTP/キャッシュプロトコルに完全に対応していなかったり、既知のバグを抱えていたりする可能性があります。
対策 3.1.5: ブラウザのアップデート
常に最新バージョンのブラウザを使用することを推奨します。ブラウザはセキュリティだけでなく、Web標準への対応やパフォーマンス改善のために頻繁にアップデートされています。
- 手順: 各ブラウザの設定メニューから「バージョン情報」や「ヘルプ」などの項目を確認し、アップデートを実行します。
3.2 サーバー側の原因と対策 (Webサーバー、アプリケーション、CDN側)
クライアント側の問題ではない場合、Webサイトを提供しているサーバー側の設定や状態に問題がある可能性が高いです。これはWebサイトの開発者や運用担当者が確認・修正する必要があります。
原因 3.2.1 キャッシュ制御ヘッダーの不備または誤設定
Webサーバー(Apache, Nginx, IISなど)やアプリケーション(PHP, Node.js, Pythonなど)が送信するHTTPレスポンスヘッダーに、キャッシュを正しく制御するための情報(Cache-Control
, Expires
, ETag
, Last-Modified
など)が含まれていない、または誤った設定がされている場合、「resource was not cached」という状況が発生しやすくなります。
- 例:
- 静的なCSSファイルや画像ファイルにも関わらず、
Cache-Control: no-cache
やno-store
が設定されている。 Cache-Control: max-age
が非常に短い、または負の値になっている。Expires
ヘッダーが過去の日付になっている。ETag
やLast-Modified
ヘッダーが正しく生成されていない、または欠落しているため、ブラウザがキャッシュの再検証を行えない。- 動的コンテンツ(例: セッションIDを含むページ、APIレスポンス)に対して、誤って強力なキャッシュヘッダーが設定されている(この場合は「resource was not cached」自体は正しくない挙動ではないが、意図せずキャッシュされずに毎回ダウンロードされる)。
- 静的なCSSファイルや画像ファイルにも関わらず、
対策 3.2.1: HTTPレスポンスヘッダーの確認と修正
ブラウザの開発者ツール(ネットワークタブ)や、curl -I <URL>
コマンドなどを使用して、問題のリソースに対するレスポンスヘッダーを確認します。
- 確認すべきヘッダー:
Cache-Control
,Expires
,Pragma
,ETag
,Last-Modified
. - 理想的な設定例 (静的ファイル):
Cache-Control: public, max-age=31536000, immutable
(長期キャッシュ、変更されないファイル向け)Cache-Control: public, max-age=86400
(1日キャッシュ、頻繁には変わらないファイル向け)ETag: "<リソースのハッシュ値など>"
Last-Modified: <最終更新日時>
- 動的コンテンツの場合: 基本的にキャッシュさせないか、非常に短い期間(
max-age=0
)とし、必ず再検証 (must-revalidate
) させる設定が適切です。Cache-Control: no-cache, must-revalidate
Expires: 0
(または過去の日付)
サーバー設定例:
-
Apache (.htaccess または httpd.conf):
“`apache
ExpiresActive On
ExpiresByType text/css “access plus 1 year”
ExpiresByType image/jpeg “access plus 1 year”
ExpiresByType image/png “access plus 1 year”
# 他のファイルタイプも同様に設定
Header set Cache-Control “public, max-age=31536000, immutable”
Header set Cache-Control “public, max-age=3600, must-revalidate”
* **Nginx (nginx.conf):**
nginx
location ~* .(css|js|jpg|jpeg|png|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control “public, max-age=31536000, immutable”;
}location ~* .(html|htm)$ {
expires 1h;
add_header Cache-Control “public, max-age=3600, must-revalidate”;
}
“`
これらの設定を適切に見直すことで、ブラウザがキャッシュを正しく利用できるようになります。
原因 3.2.2 CDN (Content Delivery Network) の設定問題
CDNを利用している場合、CDNのエッジサーバーがキャッシュを保持・配信します。CDNの設定が不適切だと、CDN自体がオリジンサーバー(元のWebサーバー)からのリソースをキャッシュしない、またはキャッシュの有効期限が短すぎる、キャッシュの無効化(Purge)が正しく行われていない、といった問題が発生する可能性があります。
対策 3.2.2: CDNキャッシュ設定の確認と調整、キャッシュのパージ
利用しているCDNの管理画面で、キャッシュに関する設定を確認します。
- 確認事項:
- キャッシュ対象となるファイルの種類(拡張子)。
- キャッシュの有効期限(TTL: Time To Live)。
- キャッシュキー(URLパラメータをキャッシュの識別子に含めるかなど)。
- オリジンサーバーから受信したHTTPヘッダーをCDNがどのように扱うか(オリジンヘッダーを尊重するか、CDN側で強制的に上書きするか)。
- 調整: 静的ファイルに対して適切なTTLを設定し、オリジンサーバーからのキャッシュヘッダーがCDNで尊重されるように設定します。
- キャッシュのパージ (Purge): オリジンサーバーでリソースを更新したにも関わらず、CDNのエッジサーバーに古いキャッシュが残っている場合、手動またはAPI経由で該当リソースのキャッシュを強制的に削除する「パージ」を実行します。これにより、CDNは次にリクエストを受けたときにオリジンサーバーから最新のリソースを取得し直します。
原因 3.2.3 オリジンサーバーの過負荷またはエラー
CDNを利用している場合でも、CDNがキャッシュを持っていない場合(初回アクセス、キャッシュ切れ、パージ後など)はオリジンサーバーにリクエストが転送されます。オリジンサーバーが過負荷状態にある、データベースエラーが発生している、アプリケーションエラーが発生しているなどの場合、リソースの応答が遅延したり、エラーレスポンス(5xx系エラーなど)を返したりすることがあります。この場合、ブラウザはリソースを取得できず、キャッシュも利用できないため表示不能となります。
対策 3.2.3: オリジンサーバーの負荷状況およびログの確認
サーバーのCPU使用率、メモリ使用量、ネットワークトラフィックなどを監視し、過負荷になっていないか確認します。Webサーバー、アプリケーション、データベースのログを確認し、エラーが発生していないか調査します。必要に応じてサーバーリソースの増強、アプリケーションコードの最適化、データベースチューニングなどを行います。
原因 3.2.4 動的コンテンツ生成時の問題
特にJavaScriptやAPI呼び出しによって後から読み込まれる動的コンテンツの場合、サーバーサイドのスクリプト実行に時間がかかったり、エラーが発生したりすることがあります。これらのリソースはキャッシュされにくい性質を持つため、応答が遅延または失敗すると、「resource was not cached」という状況とともに表示遅延やエラーが発生します。
対策 3.2.4: 動的コンテンツ生成処理の最適化とエラーハンドリング
サーバーサイドのコードをプロファイリングし、ボトルネックとなっている処理を特定・改善します。データベースクエリの最適化、外部API呼び出しの非同期化やタイムアウト設定、キャッシュ可能な動的コンテンツ(例: 頻繁に変わらないユーザー固有情報以外のデータ)の部分的なキャッシュなども検討します。サーバーサイドのエラーが発生した場合に、適切なエラーレスポンス(例: 500 Internal Server Error)を返すようにし、クライアント側でそのエラーを適切にハンドリングして代替表示を行うなどのフォールバック処理を実装します。
原因 3.2.5 Service Workerの登録/更新問題 (Progressive Web Appsなど)
Progressive Web Apps (PWA) などで利用されるService Workerは、ブラウザキャッシュとは別に独自のキャッシュ機構(Cache Storage API)を持ち、リソースのオフライン利用や高速化を実現します。しかし、Service Workerのスクリプトにバグがある、Service Workerの登録や更新が失敗している、あるいはService Workerが意図せず全てのリクエストをインターセプトしてしまい、結果的に正常なネットワークアクセスやブラウザキャッシュの利用を妨げている、といった問題が発生することがあります。
対策 3.2.5: Service Workerのデバッグと確認
ブラウザの開発者ツール(通常「Application」タブ内にService Workerセクションがあります)を使用して、Service Workerの状態を確認します。
- 確認事項:
- Service Workerが正しく登録され、アクティブになっているか。
- スクリプトにエラーが出ていないか(Consoleタブも確認)。
fetch
イベントハンドラ内で、想定通りにキャッシュの利用やネットワークリクエストのフォールバックが行われているか。
- 対策:
- Service Workerのスクリプトコードをデバッグし、エラーを修正します。
- 開発者ツールのService Workerセクションで「Update on reload」や「Bypass for network」などのオプションを試して、Service Workerの影響を切り離して問題を切り分けます。
- Service Workerのキャッシュ(Cache Storage)の内容を確認し、古いリソースが残っていたり、期待通りにキャッシュされていなかったりしないか確認します。必要に応じて手動でキャッシュを削除します。
Service Workerは強力な機能ですが、その動作は複雑になりがちです。特に更新時の挙動や、キャッシュ戦略(Cache-first, Network-firstなど)の実装に誤りがあると、リソースの読み込みに問題が発生しやすいため、慎重なデバッグが必要です。
原因 3.2.6 HTTP/2 Push の設定問題
HTTP/2のServer Push機能は、ブラウザがリソースを要求する前に、サーバーが先回りして必要と思われるリソースをブラウザに送信する機能です。これにより、ブラウザがリソースの存在を知ってからリクエストを送信するまでのラウンドトリップ時間を削減できます。しかし、不要なリソースをプッシュしたり、既にブラウザキャッシュにあるリソースをプッシュしたりすると、帯域幅の無駄遣いになり、かえってパフォーマンスを悪化させることがあります。場合によっては、プッシュされたリソースがブラウザのキャッシュと競合し、意図しない挙動を引き起こす可能性もゼロではありません。
対策 3.2.6: HTTP/2 Push 設定の見直し
HTTP/2 Pushを設定している場合は、プッシュ対象のリソースが適切か、既にブラウザキャッシュにあるリソースを重複してプッシュしていないか確認します。ブラウザはCache-Digest
ヘッダーなどを利用して持っているキャッシュ情報をサーバーに伝えることがありますが、全てのブラウザが対応しているわけではなく、実装も複雑です。多くのケースでは、HTTP/2 Pushよりも<link rel="preload">
を使用したResource Hintの方が制御が容易で効果的とされています。問題切り分けのために、一時的にHTTP/2 Pushを無効化してみることも有効です。
3.3 ネットワーク側の原因と対策
クライアントやサーバーの設定に問題がない場合、その間のネットワーク経路に問題がある可能性も考慮に入れる必要があります。
原因 3.3.1 中間プロキシやファイアウォールの干渉
企業ネットワークなどで利用されている透過型プロキシやファイアウォールが、HTTP通信やキャッシュ関連ヘッダーに干渉し、キャッシュが正しく機能しない、あるいは通信自体をブロックすることがあります。
対策 3.3.1: ネットワーク管理部門への確認
もし組織内のネットワークで発生している問題であれば、ネットワーク管理部門に、プロキシやファイアウォールによるWebアクセスへの干渉がないか確認してもらいます。特定のURLやリソースタイプに対するフィルタリング、キャッシング設定などが影響している可能性があります。
原因 3.3.2 ISPや広域ネットワークの問題
まれに、インターネットサービスプロバイダ(ISP)側のキャッシュサーバーや、経路上のネットワーク機器に問題が発生している場合、キャッシュの利用に影響が出ることがあります。
対策 3.3.2: 別のネットワーク環境での確認、ISPへの問い合わせ
可能であれば、別のネットワーク環境(例: スマートフォンのキャリア回線、別の場所のWi-Fiなど)で同じWebサイトにアクセスし、問題が再現するか確認します。もし特定のネットワークでのみ問題が発生する場合、ISPに問い合わせてネットワーク状況を確認してもらう必要があるかもしれません。
第4章 「resource was not cached」発生時の詳細な診断方法
問題の原因を特定するためには、具体的な状況証拠を集めることが不可欠です。最も強力なツールは、ブラウザの開発者ツールです。
4.1 ブラウザ開発者ツール (Networkタブ) の活用
ほとんどの最新ブラウザには開発者ツールが搭載されており、Webサイトの読み込みプロセスを詳細に分析できます。特にNetworkタブは、どのリソースがリクエストされ、どのようなレスポンスを受け取ったか、キャッシュはどのように利用されたかなどを確認するのに非常に役立ちます。
手順:
- 問題が発生するWebページを開きます。
- 開発者ツールを開きます。
- Chrome, Firefox, Edge:
F12
または右クリックメニューから「検証」/「要素を調査」。 - Safari: Safariメニュー > 環境設定 > 詳細 > 「メニューバーに”開発”メニューを表示」にチェック後、開発メニュー > Webインスペクタを表示。
- Chrome, Firefox, Edge:
- 開発者ツールのウィンドウで「Network」タブを選択します。
- Networkタブが開いた状態で、問題が発生するページをリロードします(通常リロード
F5
/Cmd+R
から試すのが良いでしょう)。強制リロードは、キャッシュを使わない前提での結果になるため、原因特定後の挙動確認などに使います。 - Networkタブに、ページ読み込み時にリクエストされた全てのリソース(HTML, CSS, JS, 画像など)のリストが表示されます。
- リストの中で、問題なくキャッシュされるべきリソース(例: CSSファイル、ロゴ画像など、静的なリソース)を探します。
- 注目すべきカラム:
- Name: リソースのファイル名またはURL。
- Status: HTTPステータスコード(例:
200 OK
,304 Not Modified
,404 Not Found
,500 Internal Server Error
など)。 - Type: リソースの種類(例:
document
,stylesheet
,script
,img
など)。 - Size: リソースのサイズ。ここに「from disk cache」や「from memory cache」と表示されていれば、キャッシュから読み込まれています。バイトサイズが表示されている場合、ネットワークからダウンロードされています。「resource was not cached」はこの状態を指します。
- Time: リソースのダウンロードにかかった時間。キャッシュから読み込まれた場合は非常に短い時間(数ミリ秒以下)になります。
- Waterfall: リソースの読み込みタイミングを示すグラフ。キャッシュから読み込まれたリソースは、ネットワーク待ち時間がなく、すぐに完了します。
- キャッシュされなかった(Sizeカラムにバイトサイズが表示されている)静的リソースをクリックして、詳細情報(Headers, Preview, Response, Timingなど)を確認します。
- 特に「Headers」タブを確認し、以下の情報を調べます。
- Request Headers: ブラウザがサーバーに送信したヘッダー。特に
If-None-Match
やIf-Modified-Since
ヘッダーが送信されているか確認します。これらはキャッシュの再検証に必要なヘッダーです。 - Response Headers: サーバーがブラウザに返信したヘッダー。
Cache-Control
,Expires
,ETag
,Last-Modified
ヘッダーがどのように設定されているか確認します。これらのヘッダーが欠落していたり、no-cache
やno-store
などが含まれていたりしないかチェックします。 - Status Code: レスポンスのステータスコードが
200 OK
である場合、キャッシュが利用されずにネットワークからダウンロードされたことを意味します。304 Not Modified
であれば、キャッシュが検証後に利用されたことを意味し、「resource was not cached」の状況ではありません。
- Request Headers: ブラウザがサーバーに送信したヘッダー。特に
診断のポイント:
- 静的なリソース(CSS, JS, 画像)が
200 OK
で返ってきており、かつSize
カラムにバイトサイズが表示されている場合は、キャッシュが使われなかったことが確定します。 - そのリソースの
Response Headers
に適切なCache-Control
やExpires
、ETag
/Last-Modified
が含まれているか確認します。ヘッダーがない、または不適切な場合は、サーバー側の設定ミスです。 Response Headers
に適切なキャッシュヘッダーが含まれているにも関わらずキャッシュが使われない場合、ブラウザ側の問題(キャッシュ破損、拡張機能)やネットワーク上の問題(プロキシなどによるヘッダー書き換え)が考えられます。Request Headers
にIf-None-Match
やIf-Modified-Since
が送信されていない場合、ブラウザがそのリソースに対してそもそもキャッシュの再検証を試みていないことを意味します。これは、前回のレスポンスでキャッシュしないように指示されたか、ブラウザキャッシュがクリアされた後である、あるいはブラウザ自体の問題の可能性があります。- サーバーが
304 Not Modified
を返すべき状況(ブラウザが送ったIf-None-Match
/If-Modified-Since
とサーバーのリソースが一致する場合)であるにも関わらず、200 OK
を返している場合、サーバー側のETag/Last-Modified処理の実装ミスや、オリジンサーバーとCDN/リバースプロキシ間のキャッシュ不整合などが考えられます。
4.2 curl
コマンドによるヘッダー確認
サーバー側でヘッダーを確認する場合や、開発者ツールが使いにくい環境では、コマンドラインツールのcurl
が役立ちます。
bash
curl -I <問題のリソースのURL>
このコマンドは、指定したURLに対してHEADリクエストを送信し、レスポンスヘッダーのみを表示します。
“`bash
例: CSSファイルのヘッダーを確認
curl -I https://www.example.com/css/style.css
HTTP/1.1 200 OK
Date: Tue, 26 Oct 2023 10:00:00 GMT
Content-Type: text/css
Content-Length: 12345
Last-Modified: Mon, 25 Oct 2023 09:00:00 GMT
ETag: “abcdef1234567890”
Cache-Control: public, max-age=31536000
Expires: Wed, 26 Oct 2024 10:00:00 GMT
その他のヘッダー…
“`
このように、サーバーが返している生のレスポンスヘッダーを確認することで、サーバー側の設定が意図通りになっているか、誤ったヘッダーが送信されていないかをチェックできます。
4.3 サーバーログの確認
Webサーバー(Apache, Nginxなど)のアクセスログやエラーログを確認することも重要です。特定のリソースに対するリクエストがサーバーに到達しているか、その際にどのようなステータスコードを返しているか、エラーが発生していないかなどが分かります。
- 確認事項:
- 該当リソースへのリクエストがログに記録されているか。
- そのリクエストに対するステータスコードが
200
または304
になっているか。もし500
などのエラーコードであれば、サーバー内部でエラーが発生しています。 - リクエストの量が増加していないか(キャッシュが効いていない結果、全てのユーザーからのリクエストがサーバーに到達している可能性がある)。
- エラーログ: PHP, Node.jsなどのアプリケーションレベルのエラー、データベース接続エラー、ファイルアクセス権限エラーなど、サーバーサイドの処理で問題が発生している場合に記録されます。
これらのログを分析することで、サーバーサイドのボトルネックやエラーを特定できます。
第5章 予防策:キャッシュ問題を未然に防ぐために
「resource was not cached」エラーへの対策だけでなく、このようなキャッシュ関連の問題を将来にわたって防ぐための予防策も重要です。
5.1 適切なキャッシュヘッダーの設定
前述の「対策 3.2.1」で詳述した通り、リソースの種類に応じて適切なCache-Control
やExpires
ヘッダーを設定することが最も重要です。
- 静的ファイル (CSS, JS, 画像, Webフォントなど):
- 長期キャッシュが基本。
max-age
を長く設定(例: 1年 = 31536000秒)。 public
を指定してプロキシやCDNでのキャッシュも許可する。- ファイルの内容が変わらない限りURLも変わらないファイルには
immutable
ディレクティブを追加すると、再検証なしで長期キャッシュされる(ブラウザサポートに依存)。 ETag
とLast-Modified
も必ず含めるように設定し、ブラウザが再検証できるようにする。
- 長期キャッシュが基本。
- HTMLファイル:
- 通常は静的ファイルより短めに設定。
max-age
を数分〜数時間程度とし、must-revalidate
を含めて常に再検証させるのが一般的です。サイトの更新頻度に応じて調整します。 - 完全にリアルタイム性が求められるページや、ユーザーごとに内容が大きく異なるページは
no-cache
またはno-store
を設定します。
- 通常は静的ファイルより短めに設定。
- APIレスポンス:
- データの鮮度に応じて設定。頻繁に変わるデータは
no-cache
または短時間キャッシュ。あまり変わらないデータは数分〜数時間キャッシュ。private
を指定してブラウザのみにキャッシュさせることも検討します(ユーザー固有の情報を含む場合)。
- データの鮮度に応じて設定。頻繁に変わるデータは
5.2 キャッシュバスト (Cache Busting) 戦略
静的ファイルを更新した際、ブラウザやCDNに古いキャッシュが残っていると、ユーザーはいつまで経っても新しいファイルを取得できません。これを防ぐために「キャッシュバスト」という手法を用います。ファイルの内容が変更されたときに、そのファイルのURLも変更するというシンプルな考え方です。
- 方法:
- ファイル名にハッシュ値やバージョン番号を含める:
style.css
をstyle.v123.css
やstyle.a1b2c3d4.css
のように変更します。HTMLや他のファイルからこの新しいファイル名を参照するようにビルドプロセスで自動化します。 - クエリ文字列としてバージョン番号やタイムスタンプを付加する:
style.css
をstyle.css?v=1.0
やstyle.css?t=1678886400
のように変更します。ただし、一部のプロキシサーバーはクエリ文字列を含むURLをキャッシュしない設定になっている場合があるため、ハッシュ値方式の方が確実です。
- ファイル名にハッシュ値やバージョン番号を含める:
キャッシュバストを適切に行うことで、ブラウザは古いキャッシュを別リソースと認識し、必ず最新のリソースをサーバーに要求するようになります。これにより、ユーザーがいつまでも古いファイルを見続ける問題を避けつつ、変更のないファイルは長期キャッシュの恩恵を受けられるようになります。
5.3 CDNの活用と適切な設定
CDNは、地理的に分散されたサーバーにコンテンツをキャッシュし、ユーザーに最も近いエッジサーバーからコンテンツを配信することで、表示速度を向上させ、オリジンサーバーの負荷を軽減します。CDNを最大限に活用するためには、以下の点に注意します。
- キャッシュ可能なリソースを正しく設定する: 静的ファイルはもちろん、適切にキャッシュヘッダーが設定された動的コンテンツもCDNでキャッシュさせられる場合があります。
- TTL (Time To Live) の設定: 各リソースタイプやディレクトリパスに対して、適切なTTLを設定します。
- キャッシュキーの設定: クエリ文字列をキャッシュキーに含めるか含めないか、または特定のクエリ文字列を無視するかなど、CDNがURLをどのようにキャッシュの識別子として扱うか細かく設定します。キャッシュバストでクエリ文字列方式を用いる場合は、CDNがそれを無視しないように設定が必要です。
- キャッシュの無効化 (Purge): コンテンツを更新した際は、迅速にCDNキャッシュをパージするワークフローを確立します。API連携などで自動化するとより効率的です。
- オリジンフェッチ設定: CDNがオリジンサーバーからリソースを取得する際の挙動(タイムアウト時間、リトライ設定など)も、オリジンサーバーの安定性と合わせて考慮します。
5.4 Service Worker の慎重な実装とテスト
Service Workerを導入する場合、そのキャッシュ戦略を慎重に設計し、複数のブラウザや環境で十分にテストする必要があります。
- Service Workerのライフサイクル: 登録、インストール、アクティベート、更新といったライフサイクルを理解し、古いService Workerと新しいService Workerが混在する期間(特に更新時)の挙動を考慮に入れます。
- キャッシュ戦略の選択: Network-first, Cache-first, Stale-while-revalidate, Cache-only, Network-only など、リソースの特性に応じた適切なキャッシュ戦略を選択します。
- エラーハンドリング:
fetch
イベントハンドラ内でエラーが発生した場合のフォールバック処理を確実に実装します。ネットワークエラー、キャッシュエラー、Service Workerスクリプト内のエラーなど、様々なケースを想定します。 - デバッグ: 開発者ツールのService WorkerタブやConsoleタブを活用して、Service Workerの動作を綿密に監視・デバッグします。
Service WorkerはWebサイトのパフォーマンスと信頼性を高める強力なツールですが、誤った実装は逆にリソースの読み込み問題を発生させやすい諸刃の剣です。
5.5 サーバーおよびCDNログの継続的な監視
サーバーのアクセスログ、エラーログに加え、CDNが提供するログや分析ツールを継続的に監視します。
- 監視項目例:
- レスポンスコードの分布(特に
200
と304
の比率 –304
が多いほどキャッシュが有効に機能していることを示唆)。 - キャッシュヒット率(CDNがキャッシュから応答したリクエストの割合)。
- エラー率(サーバーやCDNがエラーを返している割合)。
- リソースごとの転送量と応答時間。
- レスポンスコードの分布(特に
これらの指標を監視することで、キャッシュが正しく機能しているか、問題が発生し始めていないかを早期に検知できます。
第6章 まとめと今後の展望
「resource was not cached」という状況は、単なるエラーメッセージではなく、「ブラウザがキャッシュを利用せず、ネットワークからリソースを再取得した(または試みた)」という事象を示しています。この事象自体が直接Webコンテンツの表示不能を引き起こすわけではなく、その背後にある「なぜキャッシュが使われなかったのか」、そして「その結果としてネットワークからの取得が失敗したのか」という根本原因こそが問題の核心です。
本記事では、この原因がブラウザのキャッシュ破損、サーバー側の不適切なキャッシュヘッダー設定、CDNの問題、アプリケーションエラー、ネットワーク干渉など、多岐にわたることを詳細に解説しました。そして、それぞれの原因に対する具体的な対策として、ブラウザキャッシュのクリア、開発者ツールを用いたヘッダー確認と分析、サーバー設定(Apache, Nginxなど)の見直し、CDN設定の調整、Service Workerのデバッグ、そしてキャッシュバスト戦略や継続的な監視といった予防策を提示しました。
Webのパフォーマンス最適化において、キャッシュは極めて重要な要素です。適切なキャッシュ戦略は、ユーザー体験の向上、サーバー負荷の軽減、そしてコスト削減に貢献します。しかし、その設定は複雑であり、複数のレイヤー(ブラウザ、プロキシ、CDN、サーバー)にまたがるため、問題が発生した際には網羅的な視点での診断が必要となります。
将来的に、Web標準やブラウザ技術はさらに進化し、より効率的で信頼性の高いキャッシュ機構が提供されるかもしれません。HTTP/3の普及や、Service Workerのようなクライアントサイドでのより柔軟なキャッシュ制御手段は、その方向性を示しています。しかし、どのような技術が導入されても、基本的なキャッシュの考え方(有効期限、再検証、コンテンツの同一性判断)と、HTTPヘッダーを通じたクライアントとサーバー間のコミュニケーションは、引き続き中心的な役割を果たすでしょう。
Webサイトを運営する開発者や担当者は、本記事で解説したような基本的なキャッシュの仕組みと、問題発生時の診断・対策方法、そして予防策を深く理解しておくことが、安定した高速なWebサイトを提供するために不可欠です。ユーザーも、キャッシュクリアや強制リロードといった基本的な操作を知っておくことで、一時的なキャッシュ問題を自身で解決できるようになります。
「resource was not cached」という状況に直面した際には、慌てずに、まずブラウザの開発者ツールを開いてネットワークの挙動を観察することから始めてください。そこには、問題解決のための貴重なヒントが詰まっています。そして、本記事が、その複雑な挙動を読み解き、適切な対策を講じるための一助となれば幸いです。
Webコンテンツの高速表示と安定稼働を目指し、適切なキャッシュ管理を実践していきましょう。
免責事項: 本記事は一般的な情報提供を目的としており、特定の環境や状況における全ての原因および対策を網羅するものではありません。具体的な問題解決にあたっては、ご自身の環境に応じた詳細な調査と専門家への相談が必要となる場合があります。サーバー設定の変更は、Webサイトの動作に影響を与える可能性があるため、十分な知識とテストを行った上で実施してください。