Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds docs for notRestoredReasons #27947

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions files/en-us/web/api/performance_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ The following guides help you to understand key concepts of the Performance API
- [Navigation timing](/en-US/docs/Web/API/Performance_API/Navigation_timing): Measuring navigation timing of a document.
- [User timing](/en-US/docs/Web/API/Performance_API/User_timing): Measuring and recording performance data custom to your application.
- [Server timing](/en-US/docs/Web/API/Performance_API/Server_timing): Collecting server-side metrics.
- [Reporting back/forward cache not restored reasons](/en-US/docs/Web/API/Performance_API/Reporting_backforward_cache_not_restored_reasons): Reporting on whether frames present in the document were blocked from using the [back/forward cache](https://web.dev/bfcache/) (bfcache), and why.
- Paint timing
- Long task timing
- Largest contentful paint
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
title: Reporting back/forward cache not restored reasons
slug: Web/API/Performance_API/Reporting_backforward_cache_not_restored_reasons
page-type: web-api-overview
status:
- experimental
browser-compat: api.PerformanceNavigationTiming.notRestoredReasons
---

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

The {{domxref("PerformanceNavigationTiming.notRestoredReasons")}} property reports information on whether frames present in the document were blocked from using the [back/forward cache](https://web.dev/bfcache/) (bfcache) on navigation, and why. Developers can use this information to identify pages that need updates to make them bfcache-compatible, thereby improving site performance.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## Concepts and usage

Modern browsers provide an optimization feature for history navigation called the [back/forward cache](https://web.dev/bfcache/) (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.

Previously, there was no way for developers to find out why their pages were blocked from using the bfcache in the wild, though there is a [test in Chrome dev tools](https://web.dev/bfcache/#test-to-ensure-your-pages-are-cacheable). To enable monitoring in the field, the [`PerformanceNavigationTiming`](/en-US/docs/Web/API/PerformanceNavigationTiming) class has been extended to include a `notRestoredReasons` property. This returns an object containing related information on all frames present in the document:
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

- Details such as frame `id` and `name`, to help identify them in the HTML.
- Whether they were blocked from using the bfcache.
- Reasons why they were blocked from using the bfcache.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

This allows developers to take action to make those pages bfcache-compatible, thereby improving site performance.

## Examples

A [`PerformanceNavigationTiming`](/en-US/docs/Web/API/PerformanceNavigationTiming) instance can be obtained from features such as [`Performance.getEntriesByType()`](/en-US/docs/Web/API/Performance/getEntriesByType) and [`PerformanceObserver`](/en-US/docs/Web/API/PerformanceObserver).

For example, you could invoke the following function to return all `PerformanceNavigationTiming` objects currently present in the performance timeline and log their `notRestoredReasons`:

```js
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 `PerformanceNavigationTiming.notRestoredReasons` property returns an object with the following structure, which represents the blocked state of the top-level frame:

```js
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
{
blocked: true,
children: [],
id: "",
name: "",
reasons: [ "Internal Error", "Unload handler" ],
src: "",
url: "a.com"
}
```

The properties are as follows:

- `blocked`
- : A boolean value specifying whether the navigated page is blocked from using the bfcache (`true`) or not (`false`).
- `childen`
- : An array of objects representing the blocked state of any frames embedded in the top-level frame. Each object has the same structure as the parent object — this way, any number of levels of embedded frames can be represented inside the object recursively. If the frame has no children, the array will be empty.
- `id`
- : A string representing the `id` attribute value of the frame (for example `<iframe id="foo" src="...">`). If the frame has no `id`, the value will be an empty string.
- `name`
- : A string representing the `name` attribute value of the frame (for example `<iframe name="bar" src="...">`). If the frame has no `name`, the value will be an empty string.
- `reasons`
- : An array of strings each representing a reason why the navigated page was blocked from using the bfcache. There are many different reasons why blocking could occur. See the [Blocking reasons](#blocking_reasons) for more details.
- `src`
- : A string representing the path to the frame's source (for example `<iframe src="b.html">`). If the frame has no `src`, the value will be an empty string.
- `url`
- : A string representing the URL of the navigated page.

### Reporting bfcache blocking in same-origin frames

When a page has same-origin frames embedded, the returned `notRestoredReasons` value will contain an object inside the `children` property representing the blocked state of each embedded frame.

For example:

```js
{
blocked: false,
children: [
{ url: "a.com", src: "b.a.com", id: "b", name: "b", blocked: false, reasons: [], children: [] },
{ url: "a.com", src: "c.a.com", id: "c", name: "c", blocked: true, reasons: [ "BroadcastChannel" ], children: [] },
{ url: "a.com", src: "d.a.com", id: "d", name: "d", blocked: false, reasons: [], children: [] }
],
id: "",
name: "",
reasons: [],
src: "",
url:"a.com"
}
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
```

### Reporting bfcache blocking in cross-origin frames

When a page has cross-origin frames embedded, we limit the amount of information shared about them to avoid leaking cross-origin information. We only include information that the outer page already knows, and whether the cross-origin subtree blocked the bfcache or not. We don't include any blocking reasons or information about lower levels of the subtree (even if some sub-levels are same-origin).

For example:

```js
{
blocked: false,
children: [
{ url: "a.com", src: "c.a.com", id: "c", name: "c", blocked: true, reasons: [ "ScreenReader" ], children: [] },
/* cross-origin frame */
{ url: "", src: "b.com", id: "d", name: "d", blocked: true, reasons: [], children: [] }
],
id: "",
name: "",
reasons: [],
src: "",
url:"a.com"
}
```

If multiple cross-origin frames have blocking reasons, we randomly select one cross-origin frame and report whether it blocked bfcache or not. For the rest of the frames, we report `null` for the `blocked` value. This is to stop bad actors from inferring information about user state on sites they don't control by embedding multiple third-party frames into a page and then comparing the blocking information from each.

```js
{
blocked: false,
children: [
/* cross-origin frames */
{url: "", src: "b.com", id: "b", name: "b", blocked: null, reasons: [], children: []},
{url: "", src: "c.com", id: "c", name: "c", blocked: true, reasons: [], children: []},
{url: "", src: "d.com", id: "d", name: "d", blocked: null, reasons: [], children: []}
]
id: "",
name: "",
reasons: [],
src: "",
url:"a.com"
}
```

> **Note:** See the [Security and privacy](https://github.com/rubberyuzu/bfcache-not-retored-reason/blob/main/NotRestoredReason.md#security-and-privacy) section in the explainer for more details about security and privacy considerations.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## Blocking reasons

As noted earlier, there are many different reasons why blocking could occur. Google has compiled a [spreadsheet](https://docs.google.com/spreadsheets/d/1li0po_ETJAIybpaSX5rW_lUN62upQhY0tH4pR5UPt60/edit#gid=0) showing all the reason strings and explaining what they mean.
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

There are a few major categories of reasons that are worth calling out:
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

- `Circumstantial`: This refers to blocking reasons not directly related to the developer's page code. For example, a related component crashed, something went wrong with the loading process, the page is in a temporary state that can't be cached, bfcache is disabled due to insufficient memory, or a [service worker](/en-US/docs/Web/API/Service_Worker_API) did something to the page that disqualifies it from being cached.
- `Extensions`: There are a few different reason messages related to extensions. There are several different reasons combined into the "Extensions" reason. The reasons concerning extension-related blocking are intentionally vague because it would be bad for privacy to give away too much information about what extensions the user has installed, which ones are active on the page, what they are doing, etc.
- `PageSupportNeeded`: The developer's code is using a web platform feature that is otherwise not bfcache blocking, but it is currently in a state that is bfcache blocking. For example, the page currently has a [BroadcastChannel](/en-US/docs/Web/API/BroadcastChannel) with registered listeners, or an open [IndexedDB](/en-US/docs/Web/API/IndexedDB_API) connection. Or the page has registered an [`unload` handler](/en-US/docs/Web/API/Window/unload_event), which currently [prevents the bfcache from being used in some browsers](https://web.dev/bfcache/#never-use-the-unload-event).
- `SupportPending`: The developer's code is using a web platform feature that disqualifies the page from the bfcache, for example the [Web Serial API](/en-US/docs/Web/API/Web_Serial_API), [Web Authentication API](/en-US/docs/Web/API/Web_Authentication_API), [File System Access API](/en-US/docs/Web/API/File_System_Access_API), or [Media Session API](/en-US/docs/Web/API/Media_Session_API). Or the page is using [`Cache-Control: no-store`](/en-US/docs/Web/HTTP/Headers/Cache-Control), which currently [prevents the bfcache from being used in some browsers](https://web.dev/bfcache/#minimize-use-of-cache-control-no-store). This category is also used to report the presence of a tool outside the page itself that is blocking the bfcache, such as a screen reader or password manager.

## Browser compatibility

{{Compat}}
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved

## See also

- {{domxref("PerformanceNavigationTiming")}}
2 changes: 2 additions & 0 deletions files/en-us/web/api/performancenavigationtiming/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ The interface also supports the following properties:
- : A {{domxref("DOMHighResTimeStamp")}} representing the time immediately after the current document's [`load`](/en-US/docs/Web/API/Window/load_event) event handler completes.
- {{domxref('PerformanceNavigationTiming.loadEventStart')}} {{ReadOnlyInline}}
- : A {{domxref("DOMHighResTimeStamp")}} representing the time immediately before the current document's [`load`](/en-US/docs/Web/API/Window/load_event) event handler starts.
- {{domxref('PerformanceNavigationTiming.notRestoredReasons')}} {{ReadOnlyInline}}
- : An object providing report data on whether frames present in the current document were blocked from using the back/forward cache (bfcache) on navigation, and why.
- {{domxref('PerformanceNavigationTiming.redirectCount')}} {{ReadOnlyInline}}
- : A number representing the number of redirects since the last non-redirect navigation in the current browsing context.
- {{domxref('PerformanceNavigationTiming.type')}} {{ReadOnlyInline}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: "PerformanceNavigationTiming: notRestoredReasons property"
short-title: notRestoredReasons
slug: Web/API/PerformanceNavigationTiming/notRestoredReasons
page-type: web-api-instance-property
status:
- experimental
browser-compat: api.PerformanceNavigationTiming.notRestoredReasons
---

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

The **`notRestoredReasons`** read-only property returns an object providing report data on whether frames present in the current document were blocked from using the back/forward cache (bfcache) on navigation, and why.

## Value

An object containing the following properties:

- `blocked`
- : A boolean value specifying whether the navigated page is blocked from using the bfcache (`true`) or not (`false`).
- `childen`
- : An array of objects representing the blocked state of any frames embedded in the top-level frame. Each object has the same structure as the parent object — this way, any number of levels of embedded frames can be represented inside the object recursively. If the frame has no children, the array will be empty.
- `id`
- : A string representing the `id` attribute value of the frame (for example `<iframe id="foo" src="...">`). If the frame has no `id`, the value will be an empty string.
- `name`
- : A string representing the `name` attribute value of the frame (for example `<iframe name="bar" src="...">`). If the frame has no `name`, the value will be an empty string.
- `reasons`
- : An array of strings each representing a reason why the navigated page was blocked from using the bfcache. There are many different reasons why blocking could occur. See the [Blocking reasons](/en-US/docs/Web/API/Performance_API/Reporting_backforward_cache_not_restored_reasons#blocking_reasons) for more details.
- `src`
- : A string representing the path to the frame's source (for example `<iframe src="b.html">`). If the frame has no `src`, the value will be an empty string.
- `url`
- : A string representing the URL of the navigated page.

## Examples

A [`PerformanceNavigationTiming`](/en-US/docs/Web/API/PerformanceNavigationTiming) instance can be obtained from features such as [`Performance.getEntriesByType()`](/en-US/docs/Web/API/Performance/getEntriesByType) and [`PerformanceObserver`](/en-US/docs/Web/API/PerformanceObserver).

For example, you could invoke the following function to return all `PerformanceNavigationTiming` objects currently present in the performance timeline and log their `notRestoredReasons`:

```js
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);
}
}
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
```

The `PerformanceNavigationTiming.notRestoredReasons` property returns an object with the following structure, which represents the blocked state of the top-level frame:

```js
chrisdavidmills marked this conversation as resolved.
Show resolved Hide resolved
{
blocked: true,
children: [],
id: "",
name: "",
reasons: [ "Internal Error", "Unload handler" ],
src: "",
url: "a.com"
}
```

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- [Reporting back/forward cache not restored reasons](/en-US/docs/Web/API/Performance_API/Reporting_backforward_cache_not_restored_reasons)
- {{domxref("PerformanceResourceTiming")}}
3 changes: 2 additions & 1 deletion files/jsondata/GroupData.json
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,8 @@
"/docs/Web/API/Performance_API/Resource_timing",
"/docs/Web/API/Performance_API/Navigation_timing",
"/docs/Web/API/Performance_API/User_timing",
"/docs/Web/API/Performance_API/Server_timing"
"/docs/Web/API/Performance_API/Server_timing",
"/docs/Web/API/Performance_API/Reporting_backforward_cache_not_restored_reasons"
],
"interfaces": [
"EventCounts",
Expand Down