ウェブサイトを更新した際、「CSSやJavaScriptを変更したのに、ブラウザをリロードしても表示が変わらない」「スーパーリロード(Ctrl + F5 / Cmd + Shift + R)やキャッシュクリアをしないと新機能が動かない」という現象が起きることがあります。これを解決する技術がキャッシュバスター (Cache Busting) です。
1. なぜ古いファイルが読み込まれ続けるのか?
ブラウザには、一度読み込んだ画像、CSS、JavaScript、JSONなどのファイルをPCやスマホに一時保存(キャッシュ)する強力な仕組みがあります。これは、2回目以降のページ表示を高速化し、通信量を削減するための重要な機能です。
しかし、サーバー側でファイルを更新しても、ブラウザが「まだ古いキャッシュのままで大丈夫」と判断してしまうと、ユーザーの画面には古いファイルが適用されたままになってしまいます。
2. キャッシュバスターの基本的な仕組み
キャッシュバスターは、「URLの一部を変更することで、ブラウザに別のファイルであると認識させ、強制的にサーバーから再ダウンロードさせる」仕組みです。ブラウザは、URLが1文字でも異なればキャッシュを使わずに新しいファイルを要求する仕様を利用しています。
3. 主な実装方法
キャッシュバスターの実装には、いくつかのパターンがあります。
方法 A: クエリパラメータにタイムスタンプを付与する(動的制御)
JavaScriptなどで外部のJSONデータやスクリプトを動的にフェッチ(読み込み)する際に有効な方法です。URLの末尾に ?t=[タイムスタンプ] を付加します。
// 常に現在時刻(ミリ秒)をパラメータに加えることで、毎アクセスURLが変わる
const timestamp = Date.now();
fetch(`notes/index.json?t=${timestamp}`)
.then(response => response.json())
.then(data => console.log(data));
注意: 毎アクセスURLが異なるため、ブラウザキャッシュは100%効かなくなります。更新頻度が非常に高いJSONデータなどには最適ですが、静的なJSやCSSでこれをやると毎回ダウンロードが発生し、パフォーマンス低下に繋がります。
方法 B: クエリパラメータにバージョン番号を付与する(静的制御)
HTMLに直接書き込むCSSやJavaScriptリンクでよく使われます。リリースごとに ?v=[バージョン番号] を手動またはビルド時に付加します。
<!-- バージョンが変わった時だけブラウザは再読み込みする -->
<link rel="stylesheet" href="styles/site.css?v=1.0.2">
<script src="scripts/main.js?v=1.0.2"></script>
方法 C: ファイル名にハッシュ値を埋め込む(モダン開発)
WebpackやViteなどの近代的なビルドツールを使用する場合、ファイルの内容から算出された固有のハッシュ値をファイル名に自動で付与します(例:main.a8f3c2.js)。ファイルの内容が書き換わった時だけハッシュ値が変化するため、完璧なキャッシュ制御が可能です。
4. 実体験から学ぶ落とし穴:二重キャッシュの罠
トラブル事例:キャッシュバスターをJSに仕込んだのに、まだキャッシュが効いている?
今回、本サイトの記事一覧データ(index.json)に対して「方法 A (タイムスタンプの付与)」を用いてキャッシュを無効化する修正をJavaScriptファイル(main.js)に加えました。しかし、プッシュ直後はやはりキャッシュクリアをしないと新着記事が反映されない状態が続きました。原因:
データをフェッチする処理が書かれたJavaScriptファイル(main.js)自体がブラウザにキャッシュされていたためです。JSファイルが古いキャッシュのままである限り、その中に新しく書いた「キャッシュバスター付きでデータをフェッチする」という処理自体が実行されません。解決策:
HTML側でJSを読み込む箇所に「方法 B (バージョン番号の付与)」を適用し、main.js?v=1.0.1のように指定してJSファイルのキャッシュを強制クリアさせました。これにより、新しいJSファイルが読み込まれ、そこからさらにタイムスタンプ付きの最新JSONデータが読み込まれるようになり、完全な自動更新が実現しました。
5. まとめ
今回の技術ノートシステムでは、記事一覧データベースである index.json のキャッシュによる「新しい記事がトップに表示されない問題」を解決するため、**方法 A(タイムスタンプの付与)**を採用しました。これにより、トップページを開くたびに最新の記事リストが確実に取得・レンダリングされるようになっています。また、それを制御するJSファイル自体には**方法 B(バージョン付与)**でキャッシュを無効化しています。