ダブルキーキャッシュの理解:キャッシュがサイト間で共有されない理由
Takashi Yamamoto
Infrastructure Engineer · Leapcell

「あるウェブサイトで静的リソースがキャッシュされたままなのに、別のサイトからアクセスすると再ダウンロードが必要になるのはなぜだろう?」と思ったことはありませんか?
これは根本的にダブルキーキャッシュによって引き起こされています。
そこで今回は、ダブルキーキャッシュとは何か、どのように機能するのか、そしてどのように最適化できるのかを掘り下げていきましょう。
ダブルキーキャッシュとは?
従来のブラウザキャッシュでは、リソースは通常URLに基づいて保存されます。
たとえば、https://cdn.example.com/script.js
にアクセスすると、ブラウザはこのscript.js
ファイルをキャッシュします。別のウェブサイトが同じURLを参照すると、ブラウザは再度ダウンロードする必要なく、キャッシュされたバージョンを直接再利用します。
この従来のキャッシュ方法は、期待どおりに機能します。リソースがキャッシュされると、どのサイトでもアクセスできます。
ただし、このアプローチには重大なセキュリティリスクがあります。それは、クロスサイトトラッキングとデータ漏洩です。
例:
- 一部のウェブサイトは、パブリックCDNリソースのキャッシュステータスをチェックして、ユーザーが特定のサイトにアクセスしたかどうかを推測できます(例:広告トラッキング)。
- ハッカーはキャッシュポイズニング攻撃を利用して、ユーザーに侵害されたリソースを提供できます。
これらのセキュリティリスクを軽減するために、多くのブラウザ(例:ChromeやFirefox)はダブルキーキャッシュを導入しました。
ダブルキーキャッシュの核心ルールは、リソースをキャッシュするときは、URLだけでなく、それがロードされたサイト(オリジン)も考慮することです。つまり、キャッシュは**「サイト + URL」**をユニークな識別子としています。
言い換えると:
- 以前は、サイトAによってキャッシュされたリソースをサイトBが再利用できました ✅
- 現在では、サイトAによってキャッシュされたリソースはサイトBによって再ダウンロードされる必要があります ❌
ダブルキーキャッシュはどのように機能するのか?
ダブルキーキャッシュ = オリジン + リソースURL
例を使って説明しましょう:
ページAとページBにアクセスすると仮定します。どちらも同じCDNリソースを使用しています:
https://cdn.example.com/script.js
。
従来のキャッシュ(シングルキーキャッシュ)
- ページAで
script.js
をロードすると、ブラウザがファイルをキャッシュします。 - ページBにアクセスすると、ブラウザは同じ
script.js
を要求していることを認識し、キャッシュから直接ロードします(ネットワークリクエストを減らし、ロード速度を向上させます)。
ダブルキーキャッシュ
- ページAで
script.js
をロードすると、ブラウザはページAに対してのみそれをキャッシュします。 - ページBにアクセスすると、同じ
script.js
を要求していても、ブラウザはそれを完全に新しいリソースとして扱い、新たにダウンロードする必要があります。
異なるサイトが同じリソースを要求する場合でも、個別にキャッシュする必要があります!
これによりセキュリティが強化されますが、冒頭で述べた混乱も引き起こされます。リソースはサイト間で共有できず、複数回ダウンロードする必要があります。
ダブルキーキャッシュの欠点
ダブルキーキャッシュはセキュリティを向上させる一方で、いくつかの問題も引き起こします。
- キャッシュ再利用率の低下: 同じリソースであっても、異なるサイトは再ダウンロードする必要があります。
- パブリックCDNの効果の低下: 従来、CDN(jsDelivrやUNPKGなど)は、複数のサイトがキャッシュされたリソースを共有するのに役立ちました。現在、この利点は大幅に減少しています。
- 初回アクセスコストの増加: ユーザーがサイトにアクセスするとき、別のサイトからの同じリソースのキャッシュコピーを持っていても、再度ダウンロードする必要があるため、初期ページロードが遅くなります。
ダブルキーキャッシュの影響を最適化するには?
ダブルキーキャッシュの仕組みとその潜在的な欠点を理解したところで、その影響を最適化する方法を探ってみましょう。
サービスワーカーを使用する
サービスワーカーは、クライアント側のリクエストをインターセプトし、ローカルキャッシュを活用してネットワークリクエストへの依存を減らすことができます。
たとえば、Cache APIを使用して特定のリソースを手動で保存し、ダブルキーキャッシュの制限を回避できます。
self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request); }) ); });
サービスワーカーのキャッシュはダブルキーキャッシュの影響を受けないため、HTTPキャッシュに完全に依存する代わりに、それを使用して頻繁に使用される静的リソースを管理できます。
HTTP/3を使用して冗長なリクエストを削減する
ダブルキーキャッシュにより、同じユーザーが異なるウェブサイトにアクセスした場合でも、一般的なCDNリソースが複数回ダウンロードされる可能性があります。
ただし、多重化と0-RTT接続をサポートする**HTTP/3 (QUIC)**を使用すると、パフォーマンスを最適化できます。
CDNがHTTP/3をサポートしているかを確認する方法は? Chrome DevToolsを開き、Networkパネルに移動し、Protocol列を確認します。
h3
と表示されている場合、そのリソースはHTTP/3を使用しています。
クリティカルリソースをプリロードする
ブラウザのキャッシュに完全に依存できないため、積極的にクリティカルリソースをプリロードできます。
たとえば、`<link rel=