Had an issue with bfcache
Today I learned about bfcache when someone pointed out a problem on an example I did of a counter in htmx.
You load the page, counter (whose state is stored on the server) is at 0.
Increment counter, 1, 2, 3. Increment happens without a full page reload.
Go back to a previous page in your browser with the back button, then go forward again to the counter.
Counter is at 0 again.
Not because it reset, but because the browser cached the first full page load in its bfcache (back/forward cache).
You need to refresh the page to see the actual count value.
This only happened in Chrome (and Chrome-based browsers like Arc). Safari? No problem. Firefox? No problem. And also, Chrome with DevTools open with “Cache disabled” setting? No problem (that’s why I didn’t notice).
Solution?
I added these meta tags to my HTML head tag:
<meta http-equiv="Cache-Control" content="no-cache, no-store" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
I could also set them as HTTP headers, for example using Astro:
import { defineConfig } from 'astro/config'
import node from '@astrojs/node'
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone',
}),
server: {
headers: {
'Cache-Control': 'no-cache, no-store',
Pragma: 'no-cache',
Expires: '0',
},
},
})
I had a hard time testing this because I couldn’t find a good way to clear the bfcache, until I had the idea of testing in incognito mode, and I was able to see it worked fine.
Read more about bfcache: https://web.dev/articles/bfcache
Note that they suggest using
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
console.log('This page was restored from the bfcache.')
} else {
console.log('This page was loaded normally.')
}
})
to detect a page was restored but this didn’t work at all, persisted is always false and this might be a bug.
Actually it is a bug in Chrome since 2014 🥲
If the no-cache no-store header is not an option, one snippet I found on StackOverflow to reload the page if page was detected to be from the bfcache, taking into consideration Chrome’s “bug”:
window.addEventListener(
'pageshow',
function (event) {
if (
event.persisted ||
performance.getEntriesByType('navigation')[0].type === 'back_forward'
) {
location.reload()
}
},
false,
)
…not optimal, of course.
But interesting.
Never heard of bfcache before.
I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter
JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025