diff --git a/README.md b/README.md index 71431874..63728f6a 100644 --- a/README.md +++ b/README.md @@ -697,10 +697,13 @@ interface Metric { * The type of navigation * * Navigation Timing API (or `undefined` if the browser doesn't - * support that API). For pages that are restored from the bfcache, this - * value will be 'back-forward-cache'. + * support that API). + * For pages that are restored from the bfcache, this value will + * be 'back-forward-cache'. + * For pages that are restored after being discarded, this value will + * be 'restore'. */ - navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender'; + navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore'; } ``` diff --git a/src/lib/initMetric.ts b/src/lib/initMetric.ts index 63a9a665..57453bd6 100644 --- a/src/lib/initMetric.ts +++ b/src/lib/initMetric.ts @@ -30,6 +30,8 @@ export const initMetric = (name: Metric['name'], value?: number): Metric => { } else if (navEntry) { if (document.prerendering || getActivationStart() > 0) { navigationType = 'prerender'; + } else if (document.wasDiscarded) { + navigationType = 'restore'; } else { navigationType = navEntry.type.replace(/_/g, '-') as Metric['navigationType']; diff --git a/src/types.ts b/src/types.ts index 26beaba2..e75751a7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -58,9 +58,11 @@ interface PerformanceEntryMap { // Update built-in types to be more accurate. declare global { - // https://wicg.github.io/nav-speculation/prerendering.html#document-prerendering interface Document { - prerendering?: boolean + // https://wicg.github.io/nav-speculation/prerendering.html#document-prerendering + prerendering?: boolean; + // https://wicg.github.io/page-lifecycle/#sec-api + wasDiscarded?: boolean; } interface Performance { diff --git a/src/types/base.ts b/src/types/base.ts index a5145f5b..1d2d0a6a 100644 --- a/src/types/base.ts +++ b/src/types/base.ts @@ -65,7 +65,7 @@ export interface Metric { * support that API). For pages that are restored from the bfcache, this * value will be 'back-forward-cache'. */ - navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender'; + navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore'; } /** diff --git a/test/e2e/onCLS-test.js b/test/e2e/onCLS-test.js index 3a116e26..4552852f 100644 --- a/test/e2e/onCLS-test.js +++ b/test/e2e/onCLS-test.js @@ -632,6 +632,27 @@ describe('onCLS()', async function() { assert.strictEqual(cls.navigationType, 'back-forward-cache'); }); + it('reports restore as nav type for wasDiscarded', async function() { + if (!browserSupportsCLS) this.skip(); + + await browser.url('/test/cls?wasDiscarded=1'); + + // Wait until all images are loaded and rendered, then change to hidden. + await imagesPainted(); + await stubVisibilityChange('hidden'); + + await beaconCountIs(1); + const [cls] = await getBeacons(); + + assert(cls.value >= 0); + assert(cls.id.match(/^v3-\d+-\d+$/)); + assert.strictEqual(cls.name, 'CLS'); + assert.strictEqual(cls.value, cls.delta); + assert.strictEqual(cls.rating, 'good'); + assert.strictEqual(cls.entries.length, 2); + assert.strictEqual(cls.navigationType, 'restore'); + }); + describe('attribution', function() { it('includes attribution data on the metric object', async function() { if (!browserSupportsCLS) this.skip(); diff --git a/test/e2e/onFCP-test.js b/test/e2e/onFCP-test.js index 01adf266..aa065951 100644 --- a/test/e2e/onFCP-test.js +++ b/test/e2e/onFCP-test.js @@ -235,6 +235,23 @@ describe('onFCP()', async function() { assert.strictEqual(fcp2.navigationType, 'back-forward-cache'); }); + it('reports restore as nav type for wasDiscarded', async function() { + if (!browserSupportsFCP) this.skip(); + + await browser.url('/test/fcp?wasDiscarded=1'); + + await beaconCountIs(1); + + const [fcp] = await getBeacons(); + assert(fcp.value >= 0); + assert(fcp.id.match(/^v3-\d+-\d+$/)); + assert.strictEqual(fcp.name, 'FCP'); + assert.strictEqual(fcp.value, fcp.delta); + assert.strictEqual(fcp.rating, 'good'); + assert.strictEqual(fcp.entries.length, 1); + assert.strictEqual(fcp.navigationType, 'restore'); + }); + describe('attribution', function() { it('includes attribution data on the metric object', async function() { if (!browserSupportsFCP) this.skip(); diff --git a/test/e2e/onFID-test.js b/test/e2e/onFID-test.js index 97751742..f22fa5ce 100644 --- a/test/e2e/onFID-test.js +++ b/test/e2e/onFID-test.js @@ -194,6 +194,28 @@ describe('onFID()', async function() { assert.match(fid2.entries[0].name, /(mouse|pointer)down/); }); + it('reports restore as nav type for wasDiscarded', async function() { + if (!browserSupportsFID) this.skip(); + + await browser.url('/test/fid?wasDiscarded=1'); + + // Click on the