Basics of bfcache and how to detect with JavaScript
What is bfcache?
bfcache
stands for back/forward cache
and is one of the browser's caching features.
The bfcache
stores a complete snapshot of a web page in memory, including JavaScript execution status. Then, when browser's back and forward buttons (including swiping back/forward on smartphones) navigate to a different page, that page is rendered based on the bfcache
stored in memory. This allows web pages to be shown without having to request them over network, thus making them faster to display.
A typical example of this is as follows:
With a drawer menu open on a website for mobile, if you go to another page from the drawer and then swipe back to the previous page, the drawer remains open.
This could be happening because the page is rendered by bfcache
in many cases.
Please also see this video.
How to check if bfcache is enabled
In Chrome Developer tools, go to Application > Back/forward cache
menu, and click test back/forward cache
button. After a testing procedure, if it says Successfully served from back/forward cache.
, it means that the page has bfcache
enabled.
Please also see the video below for a comparison of how pages are loaded with bfcache
disabled and with bfcache
enabled.
When bfcache
is enabled, you can see that pages are not requested over network when you move to the pages using the back/forward buttons.
Note that this video was captured in Chrome's incognito mode.
Supported browsers
bfcache
is a feature initially supported by Firefox and Safari, but now supported by all major browsers, including Chrome.
Basically, bfcache
does not seem to work unless there is unload
event listener in a page, but this behavior varies among browsers.
For example, if you view the page with Firefox where bfcache
was disabled as shown in the video above, you will see that the page is rendered by bfcache
.
How to detect page displayed by bfcache
and do specific actions
When a page is shown based on bfcache
, the JavaScript also resumes from its stage at the time it left the page. Content of objects seems to be preserved as well.
Therefore, you may not want to use bfcache
if you always want to do some action on page load.
In this case, you can apply Cache-Control: no-store
so that the page is not stored in bfcache
.
Cache-Control: no-store
is an instruction not to store information in the HTTP cache
, not an instruction for bfcache
, but when this HTTP header is set, browsers have been preventing pages from being stored in the bfcache
. An article of web.dev
mentioned that there is such a history.
For more information, please see this article.
Source : Back/forward cache | Articles | web.dev
However, in the case I experienced, in iOS Safari, bfcache
was enabled even on pages with Cache-Control: no-store
applied. So the same thing was happening in the in-app browser (webview) of the iOS app.
In this case, I took a workaround by reloading the page if bfcache
is enabled.
To check if bfcache
is enabled, you can use the following code.
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
// do something if page loaded from bfcache
}
});
You can use the persisted
property because it returns true
if the page was loaded from cache.
There was, by the way, a slight difference in their explanations between the web.dev
mentioned above and the MDN
article regarding the persisted
property.
While web.dev
says it returns true
if the page is restored from bfcache
, MDN
simply says it returns true
if the page is loaded from cache, and does not mention bfcache
exactly.
Source : PageTransitionEvent: persisted property - Web APIs | MDN
Note that if Cache-Control: no-store
is set, event.persisted
will be false
with non-Safari browsers (probably), so the code in the if block
will not be executed.