Skip to content

Commit 89affdf

Browse files
authored
Merge pull request #284 from GoogleChrome/discarded-nav-type
Support 'restore' as a navigationType
2 parents 861d065 + 70e4d78 commit 89affdf

11 files changed

Lines changed: 158 additions & 6 deletions

File tree

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,13 @@ interface Metric {
697697
* The type of navigation
698698
*
699699
* Navigation Timing API (or `undefined` if the browser doesn't
700-
* support that API). For pages that are restored from the bfcache, this
701-
* value will be 'back-forward-cache'.
700+
* support that API).
701+
* For pages that are restored from the bfcache, this value will
702+
* be 'back-forward-cache'.
703+
* For pages that are restored after being discarded, this value will
704+
* be 'restore'.
702705
*/
703-
navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender';
706+
navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore';
704707
}
705708
```
706709

src/lib/initMetric.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export const initMetric = (name: Metric['name'], value?: number): Metric => {
3030
} else if (navEntry) {
3131
if (document.prerendering || getActivationStart() > 0) {
3232
navigationType = 'prerender';
33+
} else if (document.wasDiscarded) {
34+
navigationType = 'restore';
3335
} else {
3436
navigationType =
3537
navEntry.type.replace(/_/g, '-') as Metric['navigationType'];

src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ interface PerformanceEntryMap {
5858

5959
// Update built-in types to be more accurate.
6060
declare global {
61-
// https://wicg.github.io/nav-speculation/prerendering.html#document-prerendering
6261
interface Document {
63-
prerendering?: boolean
62+
// https://wicg.github.io/nav-speculation/prerendering.html#document-prerendering
63+
prerendering?: boolean;
64+
// https://wicg.github.io/page-lifecycle/#sec-api
65+
wasDiscarded?: boolean;
6466
}
6567

6668
interface Performance {

src/types/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export interface Metric {
6565
* support that API). For pages that are restored from the bfcache, this
6666
* value will be 'back-forward-cache'.
6767
*/
68-
navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender';
68+
navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore';
6969
}
7070

7171
/**

test/e2e/onCLS-test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,27 @@ describe('onCLS()', async function() {
632632
assert.strictEqual(cls.navigationType, 'back-forward-cache');
633633
});
634634

635+
it('reports restore as nav type for wasDiscarded', async function() {
636+
if (!browserSupportsCLS) this.skip();
637+
638+
await browser.url('/test/cls?wasDiscarded=1');
639+
640+
// Wait until all images are loaded and rendered, then change to hidden.
641+
await imagesPainted();
642+
await stubVisibilityChange('hidden');
643+
644+
await beaconCountIs(1);
645+
const [cls] = await getBeacons();
646+
647+
assert(cls.value >= 0);
648+
assert(cls.id.match(/^v3-\d+-\d+$/));
649+
assert.strictEqual(cls.name, 'CLS');
650+
assert.strictEqual(cls.value, cls.delta);
651+
assert.strictEqual(cls.rating, 'good');
652+
assert.strictEqual(cls.entries.length, 2);
653+
assert.strictEqual(cls.navigationType, 'restore');
654+
});
655+
635656
describe('attribution', function() {
636657
it('includes attribution data on the metric object', async function() {
637658
if (!browserSupportsCLS) this.skip();

test/e2e/onFCP-test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,23 @@ describe('onFCP()', async function() {
235235
assert.strictEqual(fcp2.navigationType, 'back-forward-cache');
236236
});
237237

238+
it('reports restore as nav type for wasDiscarded', async function() {
239+
if (!browserSupportsFCP) this.skip();
240+
241+
await browser.url('/test/fcp?wasDiscarded=1');
242+
243+
await beaconCountIs(1);
244+
245+
const [fcp] = await getBeacons();
246+
assert(fcp.value >= 0);
247+
assert(fcp.id.match(/^v3-\d+-\d+$/));
248+
assert.strictEqual(fcp.name, 'FCP');
249+
assert.strictEqual(fcp.value, fcp.delta);
250+
assert.strictEqual(fcp.rating, 'good');
251+
assert.strictEqual(fcp.entries.length, 1);
252+
assert.strictEqual(fcp.navigationType, 'restore');
253+
});
254+
238255
describe('attribution', function() {
239256
it('includes attribution data on the metric object', async function() {
240257
if (!browserSupportsFCP) this.skip();

test/e2e/onFID-test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,28 @@ describe('onFID()', async function() {
194194
assert.match(fid2.entries[0].name, /(mouse|pointer)down/);
195195
});
196196

197+
it('reports restore as nav type for wasDiscarded', async function() {
198+
if (!browserSupportsFID) this.skip();
199+
200+
await browser.url('/test/fid?wasDiscarded=1');
201+
202+
// Click on the <h1>.
203+
const h1 = await $('h1');
204+
await h1.click();
205+
206+
await beaconCountIs(1);
207+
208+
const [fid] = await getBeacons();
209+
assert(fid.value >= 0);
210+
assert(fid.id.match(/^v3-\d+-\d+$/));
211+
assert.strictEqual(fid.name, 'FID');
212+
assert.strictEqual(fid.value, fid.delta);
213+
assert.strictEqual(fid.rating, 'good');
214+
assert.strictEqual(fid.navigationType, 'restore');
215+
assert.match(fid.entries[0].name, /(mouse|pointer)down/);
216+
});
217+
218+
197219
describe('attribution', function() {
198220
it('includes attribution data on the metric object', async function() {
199221
if (!browserSupportsFID) this.skip();

test/e2e/onINP-test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,30 @@ describe('onINP()', async function() {
316316
assert.strictEqual(beacons.length, 0);
317317
});
318318

319+
it('reports restore as nav type for wasDiscarded', async function() {
320+
if (!browserSupportsINP) this.skip();
321+
322+
await browser.url('/test/inp?click=100&wasDiscarded=1');
323+
324+
const h1 = await $('h1');
325+
await h1.click();
326+
327+
await stubVisibilityChange('hidden');
328+
329+
await beaconCountIs(1);
330+
331+
const [inp] = await getBeacons();
332+
assert(inp.value >= 0);
333+
assert(inp.id.match(/^v3-\d+-\d+$/));
334+
assert.strictEqual(inp.name, 'INP');
335+
assert.strictEqual(inp.value, inp.delta);
336+
assert.strictEqual(inp.rating, 'good');
337+
assert(containsEntry(inp.entries, 'click', 'h1'));
338+
assert(interactionIDsMatch(inp.entries));
339+
assert(inp.entries[0].interactionId > 0);
340+
assert.strictEqual(inp.navigationType, 'restore');
341+
});
342+
319343
describe('attribution', function() {
320344
it('includes attribution data on the metric object', async function() {
321345
if (!browserSupportsINP) this.skip();

test/e2e/onLCP-test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,30 @@ describe('onLCP()', async function() {
373373
assert.strictEqual(lcp2.navigationType, 'back-forward-cache');
374374
});
375375

376+
it('reports restore as nav type for wasDiscarded', async function() {
377+
if (!browserSupportsLCP) this.skip();
378+
379+
await browser.url('/test/lcp?wasDiscarded=1');
380+
381+
// Wait until all images are loaded and fully rendered.
382+
await imagesPainted();
383+
384+
// Load a new page to trigger the hidden state.
385+
await browser.url('about:blank');
386+
387+
await beaconCountIs(1);
388+
389+
const [lcp] = await getBeacons();
390+
391+
assert(lcp.value > 0); // Greater than the image load delay.
392+
assert(lcp.id.match(/^v3-\d+-\d+$/));
393+
assert.strictEqual(lcp.name, 'LCP');
394+
assert.strictEqual(lcp.value, lcp.delta);
395+
assert.strictEqual(lcp.rating, 'good');
396+
assert.strictEqual(lcp.entries.length, 1);
397+
assert.strictEqual(lcp.navigationType, 'restore');
398+
});
399+
376400
describe('attribution', function() {
377401
it('includes attribution data on the metric object', async function() {
378402
if (!browserSupportsLCP) this.skip();

test/e2e/onTTFB-test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,24 @@ describe('onTTFB()', async function() {
209209
}
210210
});
211211

212+
it('reports restore as nav type for wasDiscarded', async function() {
213+
await browser.url('/test/ttfb?wasDiscarded=1');
214+
215+
const ttfb = await getTTFBBeacon();
216+
217+
assert(ttfb.value >= 0);
218+
assert(ttfb.value >= ttfb.entries[0].requestStart);
219+
assert(ttfb.value <= ttfb.entries[0].loadEventEnd);
220+
assert(ttfb.id.match(/^v3-\d+-\d+$/));
221+
assert.strictEqual(ttfb.name, 'TTFB');
222+
assert.strictEqual(ttfb.value, ttfb.delta);
223+
assert.strictEqual(ttfb.rating, 'good');
224+
assert.strictEqual(ttfb.navigationType, 'restore');
225+
assert.strictEqual(ttfb.entries.length, 1);
226+
227+
assertValidEntry(ttfb.entries[0]);
228+
});
229+
212230
describe('attribution', function() {
213231
it('includes attribution data on the metric object', async function() {
214232
await browser.url('/test/ttfb?attribution=1');

0 commit comments

Comments
 (0)