16

Browser: Firefox 6.0

I've Page A with the following setup to make sure the content is NOT stored in the bfcache of the browser:

1) $(window).unload(function(){});

2) Following HTTP headers:

<meta http-equiv="pragma" content="no-cache" /> 
<meta http-equiv="expires" content="-1" />
<meta http-equiv="cache-control" content="no-cache"/>

I've also hooked up the events pagehide and pageshow. When I am navigating away from the page, pagehide is invoked with CORRECT value for the event property persisted = false (that is what needed: no persistence in cache!)

After navigating a couple of pages, I've a window.history.go(-2); to go back to Page A. At this point, I want Firefox to poll the server for the updated version instead of displaying from the cache. The pageshow of Page A is invoked with CORRECT value for the event propertypersisted = false (meaning the page is NOT loaded from cache). BUT the page content is not the server data; it is the stale content (same as when navigating away from the page initially)! Fiddler also does not show a new request to server.

Google Chrome also exhibits the same behaviour. IE works as expected (reloads fresh data)!

Any idea what am i missing?

Thanks in advance!

Venkat
  • 785
  • 3
  • 10
  • 22

4 Answers4

14

There are multiple caches involved. There's the browser's document cache (bfache), the browser's HTTP cache, and possibly intermediate HTTP caches.

The <meta> tags you show above have absolutely no effect in current Chrome or Firefox. They may have an effect in IE.

So chances are, your page is just being read from the browser's HTTP cache.

If you really want to send no-cache HTTP headers, you should do that. But they need to be actual HTTP headers: as I said above, the <meta> tag "equivalents" do nothing.

And, importantly, any other intermediate caches are not going to be parsing your HTML so might cache things if you don't actually send the right HTTP headers.

Boris Zbarsky
  • 34,758
  • 5
  • 52
  • 55
  • 6
    Thanks! The following HTTP headers were already available: `Cache-Control: no-cache Pragma: no-cache Expires: -1` Unfortunately they didn't help either. After your reply, I revisited the headers and found that Firefox needs another header to prevent caching: http://blog.httpwatch.com/2008/10/15/two-important-differences-between-firefox-and-ie-caching/ `Cache-Control: no-cache, no-store` After adding the above header, it now works OK in IE, Firefox, Chrome & Safari. Only Opera still misbehaves by caching, but I am going to postpone that issue temporarily. – Venkat Aug 31 '11 at 09:01
  • Another note: Firefox does not store in bfcache if the site is SSL enabled! My production system is SSL whereas the DEV system is not. So the Production system works ok in Firefox WITHOUT any additional HTTP headers like the one mentioned above! – Venkat Sep 08 '11 at 09:14
  • It depends on your HTTP headers. SSL + no-cache won't get stored in bfcache, but cacheable SSL will be. – Boris Zbarsky Sep 08 '11 at 14:57
  • Correct! `no-cache` header was already present in my case. By "additional HTTP header" I meant the `no-store` header; which is not required if using SSL! – Venkat Sep 09 '11 at 12:59
8

If you set Cache-Control: "no-cache, no-store, must-revalidate" to http headers the page won't be cached in back-forward cache.

Firefox also considers event handlers on beforeunload event as a signal to not store page in BFC, but Safari ignores such handlers, so it's better to set correct http headers to indicate the nature of the page content (cacheable or variable)

Sergey P. aka azure
  • 3,993
  • 1
  • 29
  • 23
  • 1
    Thank you very much, you saved me after 3 days of research! – Brian Cannard Nov 26 '17 at 04:29
  • The HTTP headers only affect the normal cache, not the bfcache (in Firefox). To be extra sure, you need set both the header and the set the `unload` event. When pressing back, Firefox will use the bfcache, and if that doesn't work, fall back to the normal cache, so you need to make sure the page isn't cached in both. – Flimm Feb 24 '20 at 19:39
4

There are two caches to bear in mind:

The bfcache (back-forwards cache)

The bfcache (in Firefox, Safari and Chrome) stores the page in memory, including any dynamic modifications to the DOM. It is used by Firefox, Safari and Chrome when pressing back. To attempt to ensure that the page is not stored in this cache, you need to run these lines:

window.addEventListener('unload', function(){});
window.addEventListener('beforeunload', function(){});

Note that this seems to work in desktop Firefox and Chrome, but doesn't always work in desktop Safari, or Android Chrome or Android Firefox or iOS Safari.

Note that Webkit documentation calls the bfcache the "Page Cache".

The normal browser cache

Pages are cached in the normal browser cache, unless you set the proper no-store value in the Cache-Control heading. To be extra sure, send this full header:

Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private

Firefox, Safari and Chrome will first check the bfcache when pressing the back button. They will then fall back to the normal cache. So you need to both add an event listener to unload, and set this Cache-Control HTTP header. Note that using <meta> instead of the HTTP header may not work.

References:

Flimm
  • 136,138
  • 45
  • 251
  • 267
  • Does it matter if you use `window.addEventListener('unload', function(){});` or `window.onunload = function(){};` or `window.onbeforeunload = function(){};` ...? – Kevin Wheeler Feb 09 '23 at 00:39
  • @KevinWheeler All three of those have the potential of disabling the bfcache, but only in some browsers. See https://web.dev/bfcache/ – Flimm Feb 09 '23 at 06:19
3

The answer below does not work any more:

From answer on SO, adding an unload event to window causes the back/forward cache to be cleared.

UPDATE. POSSIBLE SOLUTION:

BFCache can bring surprises to developers, because at least in Firefox when moving back/forward the page does not refresh even if it was told by HTTP headers. So it's better to assume that the page will not refresh.

On the other hand, what is the difference between getting page with outdated data because of BFCache, and finding a tab in your browser that you did not reload for ages?

If you care about those kind of things, write some javascript that checks server for updates and reloads sensitive information. This is a chance to turn your problem into win ).

Community
  • 1
  • 1
Dan
  • 55,715
  • 40
  • 116
  • 154
  • back/forward cache === bfcache – Dan Mar 26 '13 at 13:23
  • 1
    I'm not able to invalid bfcache by adding `unload` event to window like `window.onunload = function () { console.log('lets unload windows');}`. Could you be a little more specific about how to do it? Thanks a lot. – Simon Apr 19 '13 at 14:24
  • I tried the sample at http://www.jakearchibald.com/jsperformance/backforwardcache/ and turns out it does not work either. – Simon Apr 19 '13 at 14:44
  • 1
    I tried $(window).unload(function(){});, still loading page from bf cache – murtza gondal Aug 29 '14 at 15:50
  • The HTTP headers only affect the normal cache, not the bfcache (in Firefox). To be extra sure, you need set both the header and set the `unload` event. When pressing back, Firefox will use the bfcache, and if that doesn't work, fall back to the normal cache, so you need to make sure the page isn't cached in both. – Flimm Feb 24 '20 at 19:40