Skip to content

Had an issue with bfcache

New Course Coming Soon:

Get Really Good at Git

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.

Are you intimidated by Git? Can’t figure out merge vs rebase? Are you afraid of screwing up something any time you have to do something in Git? Do you rely on ChatGPT or random people’s answer on StackOverflow to fix your problems? Your coworkers are tired of explaining Git to you all the time? Git is something we all need to use, but few of us really master it. I created this course to improve your Git (and GitHub) knowledge at a radical level. A course that helps you feel less frustrated with Git. Launching Summer 2024. Join the waiting list!
→ Get my HTML Handbook
→ Read my HTML Tutorial on The Valley of Code
→ Read my DOM Tutorial on The Valley of Code
→ Read my Browser Events Tutorial on The Valley of Code
→ Read my Browser APIs Tutorials on The Valley of Code

Here is how can I help you: