docs.rodeo

MDN Web Docs mirror

Monitoring bfcache blocking reasons

{{DefaultAPISidebar("Performance API")}} {{SeeCompatTable}} 

The {{domxref("PerformanceNavigationTiming.notRestoredReasons")}}  property reports information on why the current document was blocked from using the {{Glossary("bfcache")}}  on navigation. Developers can use this information to identify pages that need updates to make them bfcache-compatible, thereby improving site performance.

Back/forward cache (bfcache)

Modern browsers provide an optimization feature for history navigation called the back/forward cache ({{Glossary("bfcache")}} ). This enables an instant loading experience when users go back to a page they have already visited. Pages can be blocked from entering the bfcache or get evicted while in the bfcache for different reasons, some required by a specification and some specific to browser implementations.

To enable monitoring bfcache blocking reasons, the PerformanceNavigationTiming class includes a notRestoredReasons property. This returns a {{domxref("NotRestoredReasons")}}  object containing related information on the top-level frame and all {{htmlelement("iframe")}} s present in the document:

[!NOTE] Historically, the deprecated {{domxref("PerformanceNavigation.type")}}  property was used to monitor the bfcache, with developers testing for a type of "TYPE_BACK_FORWARD" to get an indication of the bfcache hit rate. This however did not provide any reasons for bfcache blocking, or any other data. The notRestoredReasons property should be used to monitor bfcache blocking, going forward.

Logging bfcache blocking reasons

Ongoing bfcache blocking data can be obtained using a PerformanceObserver, like this:

const observer = new PerformanceObserver((list) => {
  let perfEntries = list.getEntries();
  perfEntries.forEach((navEntry) => {
    console.log(navEntry.notRestoredReasons);
  });
});

observer.observe({ type: "navigation", buffered: true });

Alternatively, you can obtain historical bfcache blocking data using a suitable method such as Performance.getEntriesByType():

function returnNRR() {
  const navEntries = performance.getEntriesByType("navigation");
  for (let i = 0; i < navEntries.length; i++) {
    console.log(`Navigation entry ${i}`);
    let navEntry = navEntries[i];
    console.log(navEntry.notRestoredReasons);
  }
}

The code snippets shown above will log {{domxref("NotRestoredReasons")}}  objects to the console. These objects have the following structure, which represents the blocked state of the top-level frame:

{
  children: [],
  id: null,
  name: null,
  reasons: [
    { reason: "unload-listener" }
  ],
  src: "",
  url: "example.com",
}

The properties are as follows:

Reporting bfcache blocking in same-origin <iframe>s

When a page has same-origin <iframe>s embedded, the returned notRestoredReasons value will contain an array of objects inside the children property representing the blocking reasons related to each embedded frame.

For example:

{
  children: [
    {
      children: [],
      id: "iframe-id",
      name: "iframe-name",
      reasons: [],
      src: "./index.html",
      url: "https://www.example.com/iframe-examples.html"
    },
    {
      children: [],
      id: "iframe-id2",
      name: "iframe-name2",
      reasons: [
        { "reason": "unload-listener" }
      ],
      src: "./unload-examples.html",
      url: "https://www.example.com/unload-examples.html"
    },
  ],
  id: null,
  name: null,
  reasons: [],
  src: null,
  url:"https://www.example.com"
}

Reporting bfcache blocking in cross-origin <iframe>s

When a page has cross-origin frames embedded, the amount of information shared about them is limited to avoid leaking cross-origin information. Only information that the outer page already knows is included, and whether the cross-origin subtree caused bfcache blocking or not. No blocking reasons or information about lower levels of the subtree (even if some sub-levels are same-origin) are included.

For example:

{
  children: [
    {
      children: [],
      id: "iframe-id",
      name: "iframe-name",
      reasons: [],
      src: "https://www.example2.com/",
      url: null
    }
  ],
  id: null,
  name: null,
  reasons: [
        { "reason": "masked" }
  ],
  src: null,
  url:"https://www.example.com"
}

For all the cross-origin <iframe>s, no blocking reasons are reported; for the top-level frame a reason of "masked" is reported, to indicate that the reasons are being kept hidden for privacy purposes. Note that "masked" may also be used for hiding user agent-specific reasons; it doesn’t always indicate an issue in an <iframe>.

Blocking reasons

There are many different reasons why blocking could occur, and browsers can choose to implement their own specific reasons for blocking, based on how they operate. Developers should avoid depending on specific wording for reasons and be prepared to handle new reasons being added and deleted.

The initial values listed in the specification are:

Additional blocking reasons may be used by some browsers, for example:

Browser compatibility

{{Compat}} 

See also

[!NOTE] This article is adapted from Back/forward cache notRestoredReasons API by Chris Mills and Barry Pollard, originally published on developer.chrome.com in 2023 under the Creative Commons Attribution 4.0 License.

In this article

View on MDN