はじめに
各ブラウザの「戻る」ボタンを押すと、ブラウザのキャッシュをクリアしていても、
- JavaScriptでリンク遷移時にローディングアイコンをページ全体に表示
- 「戻る」ボタンを押す
- ローディングアイコンが全体に表示されたページが読み込まれる
といったことが発生する場合があります。
これはキャッシュには下記の2種類あり、ブラウザバックの場合はbfcache用の対策が必要となるためです。
- 通常のキャッシュ(ページや画像など、ブラウザの”キャッシュを削除”で削除できるもの)
- bfcache(戻る/進むボタン用のキャッシュ)
確認環境
- IE11
- iOS7
戻るボタンで不具合が起こる理由
「戻る」ボタン用のキャッシュは、JavaScriptの処理が全て完了した状態をメモリ上に保持しています。
キャッシュとしてメモリ上の情報を読み込むことで表示を高速化しているのですが、
JavaScriptの処理が終了した状態を保持しているため、読み込み時にJavaScriptが再度実行されません。
そのため、ページの初期化がされていなかったり、直前の見た目でページが表示されてしまい、不具合につながります。
対策
対象ページにonunload,onbeforeunload イベントをバインドする
各ページにJavaScriptのonunload,onbeforeunloadイベントがある場合、キャッシュを無効にすることができます。
下記のスクリプトを対象のページに読み込ませることで、「戻る」ボタンのキャッシュを無効化します。
window.onbeforeunload = function() {
// IE用。ここは空でOKです
};
window.onunload = function() {
// IE以外用。ここは空でOKです
};
onpageshowイベントでbfcacheを使用しているか判定する(iOS Safari対策)
iOS Safariでは、1の対策は効果が無いため、個別に対策が必要です。
onpageshowイベントのevent.persisted
によってbfcacheを使用しているかどうか判定できるため、
bfcacheを使用している場合のみ、特定の処理を行うようにします。
注意点として、onunloadと異なり、バインドしただけでキャッシュ対策にはなりません。
例では強制的に再読み込みを行っていますが、処理内容は症状に合わせて調整してください。
window.addEventListener("pageshow", function(event){
if (event.persisted) {
// ここにキャッシュ有効時の処理を書く
window.location.reload();
}
});
bfcacheでキャッシュされた値を書き換えるには(追記:2019/08/07)
bfcacheが有効になった際、キャッシュされた変数を更新することが可能か検証してみました。
結論として、下記のことが分かりました。(iOS Safariで検証)
- JavaScript内の変数を書き換えることはできなかった(変数を更新しようとすると、強制的に更新前の値に上書きされてしまう)
- DOM操作は可能だったため、jQueryの
.data()
などを使って、data属性上で変数を管理することで、更新は可能だった - ただし、上記手順で制御ができるのは1度だけで、再度ブラウザの戻るボタンを使って同じ画面に戻ってきた際は、書き換えることができなかった
bfcacheでキャッシュされた変数を完全にコントロールするのは難しいため、リロードをさせるのが要件として厳しい場合は、実装時にbfcacheを考慮したUIにするなどを検討する必要がありそうです。
HTTPレスポンスヘッダに no-store を追加する
「戻る」ボタンのキャッシュが原因の場合、
キャッシュを無効化する方法として挙げられる下記のmetaタグは効果がありません。
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">
こちらは未検証ですが、サーバ側でCache-Control:no-store
をレスポンスすることでもbfcacheを無効にできるようです。
2020/10/25追記:
各ブラウザごとのno-store
に関する挙動が書かれたリンクがありましたので、追記します
- Firefox:
- Safari:
- Chrome:
参考
https://msdn.microsoft.com/ja-jp/library/dn265017(v=vs.85).aspx
http://pageapps.mixi.jp/diary/view_diary.pl?page_id=287564&module_id=1624755&diary_id=626856
http://qiita.com/kyaido/items/5cf9482146b945a4bf67