Frontend Development 13 min read

Understanding Browser Back‑Forward Cache (bfcache) and Its Impact on Page Lifecycle

This article explains what the Back‑Forward Cache (bfcache) is, how it works across browsers, the page lifecycle events involved, common pitfalls that prevent caching, and practical testing methods to ensure optimal front‑end performance.

政采云技术
政采云技术
政采云技术
Understanding Browser Back‑Forward Cache (bfcache) and Its Impact on Page Lifecycle

1. What is bfcache?

bfcache (Back‑Forward Cache) is a browser mechanism supported by Safari and Chrome (Firefox disables it) that stores the entire page state in memory, allowing instant restoration when the user navigates back or forward without re‑requesting the server.

2. How bfcache Works

Page lifecycle

When a user leaves a page the following events fire:

beforeunload – may prompt the user; navigation can be cancelled.

visibilitychange (if the page is not hidden) – visibility changes.

pagehide – triggered when the browser attempts to store the page in bfcache; otherwise unload fires.

After the freeze event the page is frozen until it is restored from bfcache; no events fire during this period. If the page is later removed from the cache it is destroyed without notification.

When navigating back to the page, the following events fire:

resume – page resumes from frozen state.

pageshow – page is shown after being restored from cache.

visibilitychange (if navigation occurs in a visible tab).

bfcache workflow

Page enters bfcache: the browser saves DOM, styles, JavaScript state, etc.

Resources are cached in memory (JS files, CSS, images) for fast reuse.

Restoring from bfcache: the saved state is re‑hydrated without network requests.

Updating content: if the page changed while hidden, the browser reloads it to keep data fresh.

3. Situations Where Browsers Do Not Cache a Page

Pages that listen to unload or beforeunload events – use pagehide instead.

Pages using APIs such as WebSocket/WebRTC, IndexedDB, or ongoing fetch/XHR requests.

Pages with a main request header Cache-Control: no-store . Use no-cache or max-age=0 instead to avoid affecting bfcache eligibility.

4. Updating Data While bfcache Is Active

Listen to pageshow and pagehide . The pageshow event fires on normal load and when restored from bfcache; pagehide fires when the page is being stored. The persisted property indicates whether the page was actually cached.

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // handle data that needs refresh
  }
});
window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    // clean up sensitive data
  }
});

5. Checking bfcache Status

Chrome DevTools provides a panel to view bfcache hits. Successful state shows a green indicator; failure shows which API prevented caching.

6. Practical Testing Example

Install a local server:

npm install http-server -g // install
http-server -p8088 // start on port 8088

Test HTML (saved as test.html ) includes a list, a button that appends items, a timer that continuously adds items, and listeners for pageshow and load events to log whether the page was restored from bfcache.

<!DOCTYPE html>
<head><title>测试bfcache</title></head>
<body>
  <ul id="testParentDom"><li>1</li></ul>
  <button onclick="testClick()">按钮点击</button>
  <script>
    let i = 2;
    function testClick() {
      var p = document.createElement("li");
      p.innerHTML = i;
      i++;
      document.getElementById('testParentDom').append(p);
    }
    // timer modifies DOM
    setInterval(() => {
      var p = document.createElement("li");
      p.innerHTML = i;
      i++;
      document.getElementById('testParentDom').append(p);
    }, 1000);
    window.addEventListener('pageshow', function(event) {
      if (event.persisted) {
        console.log('This page was restored from the bfcache.');
      } else {
        console.log('This page was loaded normally.');
      }
    });
    window.addEventListener('load', function() {
      console.log('load');
    });
  </script>
</body>
</html>

Testing on Chrome, Safari, and Edge shows that the load event does not fire when the page is restored from bfcache; pending JavaScript tasks resume after restoration.

7. Compatibility and Recommendations

Avoid using window.open for pages that need bfcache; use rel="noopener" instead.

Ensure no unload / beforeunload listeners unless replaced by pagehide .

Do not keep open WebSocket, IndexedDB, or ongoing fetch connections when the page is being cached; close them in pagehide or freeze .

Conclusion

The bfcache mechanism offers developers a powerful way to improve web performance and user experience by instantly restoring page state. Understanding its lifecycle, avoiding disqualifying patterns, and using the appropriate events enables reliable caching across modern browsers.

References

https://web.dev/bfcache/

https://docs.google.com/document/d/1JtDCN9A_1UBlDuwkjn1HWxdhQ1H2un9K4kyPLgBqJUc/edit#heading=h.58d6ijfz2say

https://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

frontendweb performancebrowserpage lifecyclebfcache
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.