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

Support 'restore' as a navigationType #284

Merged
merged 5 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
```

Expand Down
2 changes: 2 additions & 0 deletions src/lib/initMetric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Expand Down
6 changes: 4 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/types/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}

/**
Expand Down
21 changes: 21 additions & 0 deletions test/e2e/onCLS-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
17 changes: 17 additions & 0 deletions test/e2e/onFCP-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
philipwalton marked this conversation as resolved.
Show resolved Hide resolved
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();
Expand Down
22 changes: 22 additions & 0 deletions test/e2e/onFID-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 <h1>.
const h1 = await $('h1');
await h1.click();

await beaconCountIs(1);

const [fid] = await getBeacons();
assert(fid.value >= 0);
assert(fid.id.match(/^v3-\d+-\d+$/));
assert.strictEqual(fid.name, 'FID');
assert.strictEqual(fid.value, fid.delta);
assert.strictEqual(fid.rating, 'good');
assert.strictEqual(fid.navigationType, 'restore');
assert.match(fid.entries[0].name, /(mouse|pointer)down/);
});


describe('attribution', function() {
it('includes attribution data on the metric object', async function() {
if (!browserSupportsFID) this.skip();
Expand Down
24 changes: 24 additions & 0 deletions test/e2e/onINP-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,30 @@ describe('onINP()', async function() {
assert.strictEqual(beacons.length, 0);
});

it('reports restore as nav type for wasDiscarded', async function() {
if (!browserSupportsINP) this.skip();

await browser.url('/test/inp?click=100&wasDiscarded=1');

const h1 = await $('h1');
await h1.click();

await stubVisibilityChange('hidden');

await beaconCountIs(1);

const [inp] = await getBeacons();
assert(inp.value >= 0);
assert(inp.id.match(/^v3-\d+-\d+$/));
assert.strictEqual(inp.name, 'INP');
assert.strictEqual(inp.value, inp.delta);
assert.strictEqual(inp.rating, 'good');
assert(containsEntry(inp.entries, 'click', 'h1'));
assert(interactionIDsMatch(inp.entries));
assert(inp.entries[0].interactionId > 0);
assert.strictEqual(inp.navigationType, 'restore');
});

describe('attribution', function() {
it('includes attribution data on the metric object', async function() {
if (!browserSupportsINP) this.skip();
Expand Down
24 changes: 24 additions & 0 deletions test/e2e/onLCP-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,30 @@ describe('onLCP()', async function() {
assert.strictEqual(lcp2.navigationType, 'back-forward-cache');
});

it('reports restore as nav type for wasDiscarded', async function() {
if (!browserSupportsLCP) this.skip();

await browser.url('/test/lcp?wasDiscarded=1');

// Wait until all images are loaded and fully rendered.
await imagesPainted();

// Load a new page to trigger the hidden state.
await browser.url('about:blank');

await beaconCountIs(1);

const [lcp] = await getBeacons();

assert(lcp.value > 0); // Greater than the image load delay.
assert(lcp.id.match(/^v3-\d+-\d+$/));
assert.strictEqual(lcp.name, 'LCP');
assert.strictEqual(lcp.value, lcp.delta);
assert.strictEqual(lcp.rating, 'good');
assert.strictEqual(lcp.entries.length, 1);
assert.strictEqual(lcp.navigationType, 'restore');
});

describe('attribution', function() {
it('includes attribution data on the metric object', async function() {
if (!browserSupportsLCP) this.skip();
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/onTTFB-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,24 @@ describe('onTTFB()', async function() {
}
});

it('reports restore as nav type for wasDiscarded', async function() {
await browser.url('/test/ttfb?wasDiscarded=1');

const ttfb = await getTTFBBeacon();

assert(ttfb.value >= 0);
assert(ttfb.value >= ttfb.entries[0].requestStart);
assert(ttfb.value <= ttfb.entries[0].loadEventEnd);
assert(ttfb.id.match(/^v3-\d+-\d+$/));
assert.strictEqual(ttfb.name, 'TTFB');
assert.strictEqual(ttfb.value, ttfb.delta);
assert.strictEqual(ttfb.rating, 'good');
assert.strictEqual(ttfb.navigationType, 'restore');
assert.strictEqual(ttfb.entries.length, 1);

assertValidEntry(ttfb.entries[0]);
});

describe('attribution', function() {
it('includes attribution data on the metric object', async function() {
await browser.url('/test/ttfb?attribution=1');
Expand Down
19 changes: 19 additions & 0 deletions test/views/layout.njk
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@
});
}

/**
* @return {Promise<void>}
*/
self.__stubWasDiscarded = () => {
return new Promise((resolve) => {
// Only stub if the page isn't actually discarded.
if (!document.wasDiscarded) {
Object.defineProperty(document, 'wasDiscarded', {
value: true,
configurable: true,
});
}
});
}

// Uncomment to stub running in a browser that doesn't support performance APIs
// (e.g. some version of Opera support this).
// delete self.performance;
Expand Down Expand Up @@ -131,6 +146,10 @@
if (params.has('prerender')) {
self.__stubPrerender();
}

if (params.has('wasDiscarded')) {
self.__stubWasDiscarded();
}
}());
</script>
{% if polyfill %}
Expand Down