●キャッシュバスティングとは?
皆さん、Webサイトの表示が遅かったり、更新しているのに古いページが表示されたりした経験はありませんか?
実はその原因の多くが、ブラウザのキャッシュが関係しているんです。
キャッシュは、一度表示したWebページのデータを保存しておく仕組みで、サーバーへのアクセスを減らし、表示速度を上げる効果があります。
でも、更新したのに古いページが表示されるなど、デメリットもあるんですよね。
そこで登場するのが、キャッシュバスティング。
JavaScriptを使って、キャッシュを無効化したり、更新されたことをブラウザに伝えたりする技術です。
これにより、意図しない古いページ表示を防ぎ、常に最新のWebサイトを見せることができるんです。
○キャッシュのメリットとデメリット
キャッシュには、表示速度の向上というメリットがあります。
一度表示したページのデータを保存しておくことで、再度アクセスした時にサーバーからデータを取得する必要がなくなるんです。
特にモバイルネットワークでは、通信速度や容量の節約にも繋がります。
ただ、そうは言ってもデメリットもあります。
例えば、Webサイトを更新しているのに、古いキャッシュが表示されて混乱を招くこともあるでしょう。
JavaScriptやCSSのファイルを修正しても、キャッシュが原因で反映されないなんてことも。
また、キャッシュが残っていると、個人情報の漏洩リスクもあります。
他人に見られては困るようなページまでキャッシュに残ってしまうのは避けたいですよね。
○キャッシュバスティングが必要なケース
じゃあ、具体的にキャッシュバスティングが必要になるのはどんな時でしょうか。
まず、Webサイトのリニューアルや更新をした時。
せっかく新しいデザインにしたのに、古いページが表示されてはガッカリですからね。
スムーズに移行するためにもキャッシュクリアは大切です。
それから、JavaScriptやCSSを修正した時も同様。
ファイル名は同じでも中身は変わるので、キャッシュを無効にしておかないと意図しない動作になります。
バージョン管理もしっかりしておきたいところ。
ECサイトなど、在庫情報やショッピングカートの中身など、リアルタイム性が求められるページでもキャッシュは厄介です。
古い情報を参照して、在庫切れ商品を注文してしまったりしたら大変ですからね。
他にも、ユーザー認証が必要なページでは、他のユーザーのキャッシュが表示されないように注意が必要。
あとは、広告表示など動的に変化するコンテンツにもキャッシュバスティングが有効だったりします。
●タイムスタンプを使ったキャッシュクリア
さて、キャッシュバスティングの具体的な方法を見ていきましょう。
まずは、タイムスタンプを使ったキャッシュクリアです。
タイムスタンプというのは、その名の通り、ある特定の時刻を表す数値のこと。
URLの末尾にこのタイムスタンプを付与することで、キャッシュを無効化するんです。
ブラウザは、URLが変わるとそれを別のファイルとして認識するので、サーバーから新しいファイルを取得しようとします。
○サンプルコード1:URLにタイムスタンプを追加
では早速、サンプルコードを見てみましょう。
JavaScriptのDate()オブジェクトを使って、現在のタイムスタンプを取得し、URLの末尾に付与します。
こんな感じで、script.jsというファイルのURLの末尾に、?t=タイムスタンプという形式で追加するわけです。
このURLを使ってscriptタグを生成すれば、キャッシュが無効化されて、常に最新のファイルが読み込まれるようになります。
○サンプルコード2:HTMLのscriptタグにタイムスタンプ
続いて、HTMLファイルのscriptタグにタイムスタンプを付与する方法です。
今度は、PHPのtime()関数を使って、HTMLの生成時にタイムスタンプを埋め込んでいます。
こうすることで、HTMLファイル自体のキャッシュは残ったとしても、JavaScriptファイルは常に最新版を読み込むことができますね。
○注意点とデメリット
ただ、タイムスタンプを使う方法にも注意点があります。
例えば、タイムスタンプの値が変わるたびに、ブラウザはファイルを新しいものとして扱うので、毎回サーバーからダウンロードすることになります。
つまり、ファイルが更新されていなくても、アクセスのたびにダウンロードが発生してしまうんです。
キャッシュの恩恵が受けられなくなるので、逆にパフォーマンスが低下するデメリットもあるので気をつけましょう。
また、ブラウザのキャッシュだけでなく、CDNのキャッシュにも影響してしまう点も頭に入れておく必要があります。
このように、タイムスタンプを使ったキャッシュクリアは手軽に実装できる反面、デメリットもあることを理解した上で使い分けていくことが大切ですね。
状況に応じて適切な方法を選択していきましょう。
●バージョン番号を使ったキャッシュクリア
タイムスタンプを使う方法の次は、バージョン番号を使ったキャッシュクリアについて見ていきましょう。
こちらの方が、より実用的でメジャーな手法だと思います。
バージョン番号というのは、ファイルのバージョンを表す番号のこと。
例えばscript.js?ver=1.0みたいな感じで、URLの末尾に付与します。
ファイルの中身が変更されたら、このバージョン番号を上げることで、新しいファイルとして認識させるわけですね。
○サンプルコード3:URLにバージョン番号を追加
まずは、手動でバージョン番号を付与する方法から。
先ほどのタイムスタンプの例とほぼ同じ要領ですが、タイムスタンプの代わりにバージョン番号を指定しています。
ファイルの更新に合わせてこのバージョン番号を1.1、1.2のように上げていけば、キャッシュクリアができるというわけ。
ただ、こうやって手動でバージョン番号を付与するのは、正直めんどくさいですよね。
更新のたびに書き換えるのは面倒だし、うっかりミスも怖い。
○サンプルコード4:ビルドツールでバージョン番号を自動付与
そこで、ビルドツールを使って自動化するのがおすすめです。
例えば、webpackならこんな感じ。
output.filenameに[contenthash]を指定することで、ファイルの内容が変更されるたびにユニークなハッシュ値が自動で付与されるようになります。
こうすれば、バージョン番号を手動で管理する必要がなくなるので、とても楽ちんですね。
●ランダム文字列を使ったキャッシュクリア
キャッシュクリアの方法として、もう1つ有効なのがランダム文字列を使う方法です。
バージョン番号の代わりに、ランダムな文字列をURLに付与することで、キャッシュを無効化するんですね。
ランダム文字列を使うメリットは、推測が難しいこと。
バージョン番号だと連番になりがちですが、ランダムな文字列なら予測できないので、より確実にキャッシュを無効化できるんです。
○サンプルコード6:URLにランダム文字列を追加
では早速、JavaScriptでランダム文字列を生成し、URLに付与する方法を見てみましょう。
Math.random()で0から1未満のランダムな小数を生成し、toString(36)で36進数の文字列に変換します。
substring(7)で、先頭の”0.”の7文字を除いた部分を取り出すことで、ランダムな英数字の文字列が得られるわけですね。
こうして生成したランダム文字列を、URLの末尾にクエリパラメータとして付与するだけ。
とてもシンプルですが、これだけでキャッシュを効果的に無効化できるんです。
○サンプルコード7:ランダム文字列生成関数
もちろん、毎回このコードを書くのは面倒ですよね。
そこで、ランダム文字列を生成する関数を用意しておくと便利です。
こんな感じで、generateRandomString()という関数にしておけば、必要な時にいつでも呼び出せます。
コードの見通しも良くなるので、ぜひ活用してみてください。
●その他の方法
JavaScriptを使ったキャッシュクリアの方法はまだまだあります。
ここからは、ちょっと変わった方法を3つご紹介しますね。
○サンプルコード8:メタタグでキャッシュ無効化
まずは、HTMLのmetaタグを使って、キャッシュを無効化する方法です。
こんな感じで、Cache-Controlをno-cacheに設定すれば、ブラウザはキャッシュを使わずに、毎回サーバーからファイルを取得するようになります。
ただ、この方法はHTMLファイル自体のキャッシュは無効化できるんですが、読み込んでいるJavaScriptやCSSファイルのキャッシュまでは制御できません。
あくまで部分的な対応策だと思っておきましょう。
○サンプルコード9:.htaccessでキャッシュ設定
次は、.htaccessファイルを使って、キャッシュ設定をサーバー側で制御する方法です。
こんな感じで、.htaccessファイルにキャッシュ関連のヘッダー情報を追加するんです。
Cache-Controlをno-cache、no-store、must-revalidateに設定し、Pragmaをno-cache、Expiresを0に設定することで、キャッシュを無効化できます。
ただ、この方法はApacheサーバーを使っている場合に限られます。
Nginxなど他のサーバーだと、また別の設定方法が必要になるので注意してくださいね。
●よくあるエラーと対処法
さて、ここまでキャッシュクリアの様々な方法を見てきましたが、実際に実装する際には、うまくいかないことも多いのが現実です。
ここからは、よくあるエラーとその対処法について解説していきます。
○キャッシュクリアされない場合のチェックポイント
キャッシュクリアがうまくいかない場合、まずは原因を特定することが大切です。
原因が分からないと、対処のしようがありませんからね。どこに問題があるのかを切り分けていく必要があります。
例えば、JavaScriptのコードは合っているのに、キャッシュが残ってしまう場合、サーバー側の設定が怪しいと考えられます。
逆に、コード自体に誤りがあれば、そもそもキャッシュクリアの処理が動いていない可能性が高いですよね。
ですから、こんな風にステップバイステップで確認していくのがおすすめです。
まずはJavaScriptのコードが正しく動作しているか、consol.logなどでデバッグしてみましょう。
次に、開発者ツールのNetworkタブで、本当にキャッシュが無効になっているかを確認します。
Cache-Controlヘッダーなどをチェックするんです。
それでもダメなら、サーバー側の設定を疑ってみる。
キャッシュ関連のヘッダーがちゃんと返ってきているか、htaccessなどの設定は合っているかを確認しましょう。
このように、フロントエンドとバックエンド、両面から地道にチェックしていくことが大切ですよ。
○ブラウザ毎のキャッシュクリア方法
また、ブラウザによってキャッシュの仕組みが微妙に異なるのも、トラブルの原因になりがちです。
例えば、ChromeとSafariでは、キャッシュの保存場所や有効期限の仕様が違ったりします。
そのため、一つのブラウザではキャッシュクリアできても、別のブラウザだとうまくいかない、なんてことも。
Chromeの場合は、アドレスバーにchrome://settings/clearBrowserData
と入力すると、キャッシュクリアのページに直接アクセスできます。
Safariなら、「Safari」メニューから「履歴」→「履歴とウェブサイトデータを消去」を選択する、といった具合に、ブラウザごとに操作が異なります。
●キャッシュコントロールの応用例
ここまでは、キャッシュを無効化する方法ばかりでしたが、逆にキャッシュを活用する方法もあります。
うまくキャッシュをコントロールすることで、パフォーマンス向上やサーバー負荷軽減につなげられるんです。
そんな応用例を見ていきましょう。
○サンプルコード11:キャッシュ有効期限の設定
例えば、頻繁に更新されないファイルなら、キャッシュの有効期限を長めに設定するのがおすすめ。
そうすれば、一度キャッシュされたファイルが何度もサーバーから取得されずに済むので、通信量やサーバー負荷を減らせます。
キャッシュ有効期限は、Expiresヘッダーを使って設定できます。
mod_expiresを有効にした上で、画像(jpg)とCSSファイルのキャッシュ有効期限を1ヶ月に設定しています。
「access plus 1 month」の部分を変更することで、期間の調整が可能ですよ。
○サンプルコード12:動的コンテンツのキャッシュ抑制
逆に、頻繁に更新される動的コンテンツでは、キャッシュを抑制したい場合も。
古い情報がキャッシュされていると、ユーザーが最新の情報を見られなくなってしまうからです。
PHPなどサーバーサイドで動的に生成されるページでは、こんな感じでキャッシュ関連のヘッダーを送信しましょう。
Cache-Controlヘッダーでキャッシュを無効化し、Pragmaヘッダーでもキャッシュを禁止、Expiresヘッダーでキャッシュ期限を過去に設定しています。
これで、動的コンテンツがブラウザにキャッシュされるのを防げますね。
○サンプルコード13:ユーザー認証後のキャッシュクリア
また、ユーザー認証が必要なページでは、ログイン後にキャッシュをクリアするのが一般的。
ログイン前のキャッシュが残っていると、個人情報が漏洩する恐れがあるためです。
ログイン処理を行うPHPでは、こんな感じでキャッシュ関連のヘッダーを送信します。
ログインに成功した後、Cache-Controlヘッダーなどを使ってキャッシュを無効化しているのがポイントですね。
これで、ログイン前のページがキャッシュに残ることを防げます。
まとめ
JavaScriptを使ったキャッシュクリアの方法を14個ご紹介しましたが、キャッシュバスティングの重要性と様々な実装方法が理解できたのではないでしょうか。
イムスタンプやバージョン番号を使う手軽な方法から、ビルドツールやサーバーサイドの設定を活用する高度な方法まで、プロジェクトの要件に合わせて適切な方法を選択することが大切です。
キャッシュクリアがうまくいかない場合のチェックポイントや、ブラウザごとの違いにも注意が必要ですね。
また、キャッシュを活用する応用編では、コンテンツの特性に応じたキャッシュの使い分けがポイントです。
JavaScriptのキャッシュ制御は奥が深いですが、基本的な方法をマスターすれば大抵の場面には対応できるはず。
ただし、キャッシュの状態は定期的に確認しつつ、柔軟に運用していくことが肝心。
この知識を実際のプロジェクトに活かして、パフォーマンスの高いWebサイトを構築していきましょう。