あなたはこんな疑問を持ったことがありますか?
「ウェブサイトの静的リソースはキャッシュされているのに、別のサイトを開くと再ダウンロードされるのはなぜ?」
この現象の本質的な原因は ダブルキーキャッシュ(Double-keyed Caching) にあります。
そこで、今日は ダブルキーキャッシュとは何か、どのように動作するのか、そしてどのように最適化できるのか について話しましょう。
ダブルキーキャッシュとは?
従来のブラウザキャッシュでは、リソースのキャッシュは URL に基づいて 保存されていました。
たとえば、https://cdn.example.com/script.js にアクセスすると、ブラウザはこの script.js
をキャッシュし、他のサイトが同じ URL を参照した場合は、キャッシュを再利用して再ダウンロードを防ぎます。
この従来のキャッシュ方式は、理想的な動作のように見えます。つまり、「一度キャッシュされたリソースは、どのサイトからでもアクセスできる」というものです。
しかし、この方法には 重大なセキュリティリスク が存在します。それは クロスサイトトラッキング(Cross-site Tracking) や データ漏洩 の危険性です。
例えば:
- あるウェブサイトが、共通の CDN リソースのキャッシュ状態を確認することで、ユーザーが特定のサイトを訪問したかどうかを推測できる(広告トラッキングなど)。
- ハッカーが キャッシュポイズニング(Cache Poisoning) 攻撃を利用し、ユーザーに改ざんされたリソースを読み込ませる。
このようなセキュリティ問題を防ぐため、多くのブラウザ(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 を訪問すると、ブラウザは ウェブページ A のキャッシュを使わず、再ダウンロードを行う。
つまり、異なるサイトでは、同じリソースであっても個別にキャッシュする 必要があります。
この方式は セキュリティを強化 しますが、以下のようなデメリットもあります:
- キャッシュの再利用率が低下:同じリソースでも、異なるサイトごとに再ダウンロードが必要。
- CDN の利点が減少:従来、CDN(例:jsDelivr、UNPKG)を使うことで、複数サイト間でキャッシュを共有できたが、その効果が薄れる。
- 初回アクセス時のコスト増加:同じリソースがローカルにキャッシュされていても、別のサイトでは再ダウンロードが必要になり、ページの初回読み込みが遅くなる。
ダブルキーキャッシュの影響を最適化する方法
上記の問題を考慮し、ダブルキーキャッシュの影響を最小限に抑える方法を紹介します。
① Service Worker を活用する
Service Worker を利用すれば、ローカルキャッシュを活用し、ネットワークリクエストを減らすことが可能です。
例えば、以下のような Cache API
を用いたコードを実装すると、ダブルキーキャッシュの影響を受けずにリソースをキャッシュできます:
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
Service Worker のキャッシュはダブルキーキャッシュの影響を受けない ため、頻繁に使用する静的リソースは HTTP キャッシュではなく、Service Worker で管理すると良いでしょう。
② HTTP/3 を活用し、リクエストのオーバーヘッドを削減
ダブルキーキャッシュの影響で、同じユーザーが異なるサイトを訪問すると、CDN リソースが何度もダウンロードされます。
しかし、HTTP/3(QUIC) を使えば、マルチプレクシング(多重化) や 0-RTT(ゼロ往復時間)接続 を利用して、ネットワークオーバーヘッドを削減できます。
自分の CDN が HTTP/3 に対応しているかを確認する方法
Chrome DevTools の Network タブを開き、Protocol 列を確認。
h3
と表示されていれば、HTTP/3 で通信されています。
③ 重要なリソースを事前読み込みする
ブラウザのキャッシュに完全に依存できないため、重要なリソースは明示的にプリロード するのが有効です。
例えば、以下のように <link rel="preload">
を使ってフォントやスクリプトを事前読み込みできます:
<link
rel="preload"
href="https://your-cdn.com/fonts/Roboto.woff2"
as="font"
type="font/woff2"
crossorigin="anonymous"
/>
この方法を使うことで、ダブルキーキャッシュの影響でリソースが再ダウンロードされても、できるだけ高速に読み込めるようにする ことができます。
まとめ
ダブルキーキャッシュは セキュリティ向上 のために導入された仕組みですが、キャッシュの再利用が制限されることで、パフォーマンスに影響を及ぼす 可能性があります。
そこで、Service Worker の活用、HTTP/3 の利用、重要リソースのプリロード などの方法を駆使し、影響を最小限に抑えることが重要です。
私たちはLeapcell、バックエンド・プロジェクトのホスティングの最適解です。
Leapcellは、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです:
複数言語サポート
- Node.js、Python、Go、Rustで開発できます。
無制限のプロジェクトデプロイ
- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。
比類のないコスト効率
- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。
洗練された開発者体験
- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。
簡単なスケーラビリティと高パフォーマンス
- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。
Xでフォローする:@LeapcellHQ