bfcacheの基本とJavacSriptによる検知方法
bfcacheとは
bfcache
は、back/forward cache
の略で、ブラウザのキャッシュ機能のひとつです。
bfcache
は、ウェブページの完全なスナップショットをJavaScriptの実行状況も含めてメモリに保存します。そして、ブラウザの戻るボタンや進むボタン(スマートフォンではスワイプによる戻る/進むも含む)によって、ページが遷移すると、そのページはメモリに保存された bfcache
をもとに表示されます。ウェブページをネットワークを介してリクエストせずに表示できるため、高速にページを表示できます。
よく見かける例に、次のようなものが挙げられます。
スマートフォンサイトのドロワーメニューを開いた状態で、別のページに移動した後、スワイプして前のページに戻るとドロワーが開いたままになっている。
この現象は多くの場合 bfcache
によってページが表示されているためだと考えられます。
こちらの動画もご覧ください。
bfcache が有効化どうかを確認する方法
Chromeのデベロッパーツールで、Application > Back/forward cache
の画面に表示される test back/forward cache
ボタンをクリックして、Successfully served from back/forward cache.
と表示されれば、そのページは bfcache
が有効になっている事を意味します。
bfcache
の無効のページと、有効のページの、ページの表示のされ方を比較しましたので、以下の動画もご覧ください。
bfcache
が有効の場合は、戻る/進むボタンでページを移動すると、ページ自体がリクエストされていない事が分かります。
なお、この動画は、Chromeのシークレットモードでキャプチャしています。
サポートしているブラウザ
bfcache
は、元々はFirefoxやSafariでサポートされていた機能ですが、現在はChromeをはじめ主要なブラウザがサポートしているようです。
基本的には、 ページ内に unload
イベントリスナーが存在する場合を除いて、bfcache
は動作しないようですが、この挙動は各ブラウザによって異なります。
例えば、前述の動画で bfcache
が無効だったページを、Firefoxで表示すると bfcache
によってページが表示されている事が確認できます。
bfcache
によるページ表示を検知して特定の処理を行う方法
bfcache
を元にページが表示されると、JavaScriptも、そのページを離れた時点の段階から再開されます。オブジェクトの状態も保持されるようです。
そのため、ページロード時に必ず何らかの処理を行いたい場合などは、 bfcache
を使ってほしくない時があります。
その場合は、 Cache-Control: no-store
を適用する事で、ページが bfcache
に保存されなくなります。
Cache-Control: no-store
は 情報を HTTP cache
に保存しないという指示で、 bfcache
に対する指示ではないようですが、このHTTPヘッダーがセットされると、ブラウザは ページをbfcache
に保存しないようにしてきたようです。そういう歴史があると、 web.dev
の記事で紹介されていました。
詳しくはこちらの記事をご覧ください。
Source : Back/forward cache | Articles | web.dev
ただ、 私が経験した事例では、iOS Safariの場合は、 Cache-Control: no-store
を適用したページでも bfcache
が有効になっていました。そのため、iOSアプリのアプリ内ブラウザ(webview)でも同様の現象が起きていました。
この場合は、bfcache
が有効な場合は、ページをリロードさせるという処理を行う事で対策を行いました。
bfcache
が有効かどうかは、以下のコードでチェックします。
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
// do something if page loaded from bfcache
}
});
persisted
プロパティは、ページがキャッシュからロードされた場合に true
を返すため、これを利用します。
なお、persisted
プロパティについて、前述の web.dev
では、bfcache
からページが復元された場合に true
を返すと書いてある一方で、 MDN
では、単に、キャッシュからページがロードされている場合に true
を返すと解説されていて、厳密に bfcache
とは言及されていませんでした。
Source : PageTransitionEvent: persisted property - Web APIs | MDN
なお、(恐らく)Safari以外では Cache-Control: no-store
がセットされていれば、 event.persisted
は false
になるため ifブロック
内のコードは実行されません。