Skip to content

Commit

Permalink
Allow reportAllChanges for LCP for late loaded script (#468)
Browse files Browse the repository at this point in the history
* Allow reportAllChanges for LCP for late loaded script

* Lock puppeteer as a test

* Even older version

* Revert puppeteer lock

* Review feedback

* Update src/onLCP.ts

* Update src/onLCP.ts

* Add console log to see what's going on

* More logging

* Explanation

* Revert debugging

* Missed one

---------

Co-authored-by: Philip Walton <[email protected]>
  • Loading branch information
tunetheweb and philipwalton authored May 3, 2024
1 parent 62d1436 commit 56e49c9
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 22 deletions.
20 changes: 11 additions & 9 deletions src/onLCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,26 @@ export const onLCP = (onReport: LCPReportCallback, opts?: ReportOpts) => {
let report: ReturnType<typeof bindReporter>;

const handleEntries = (entries: LCPMetric['entries']) => {
const lastEntry = entries[entries.length - 1] as LargestContentfulPaint;
if (lastEntry) {
// If reportAllChanges is set then call this function for each entry,
// otherwise only consider the last one.
if (!opts!.reportAllChanges) {
entries = entries.slice(-1);
}

entries.forEach((entry) => {
// Only report if the page wasn't hidden prior to LCP.
if (lastEntry.startTime < visibilityWatcher.firstHiddenTime) {
if (entry.startTime < visibilityWatcher.firstHiddenTime) {
// The startTime attribute returns the value of the renderTime if it is
// not 0, and the value of the loadTime otherwise. The activationStart
// reference is used because LCP should be relative to page activation
// rather than navigation start if the page was prerendered. But in cases
// where `activationStart` occurs after the LCP, this time should be
// clamped at 0.
metric.value = Math.max(
lastEntry.startTime - getActivationStart(),
0,
);
metric.entries = [lastEntry];
metric.value = Math.max(entry.startTime - getActivationStart(), 0);
metric.entries = [entry];
report();
}
}
});
};

const po = observe('largest-contentful-paint', handleEntries);
Expand Down
36 changes: 23 additions & 13 deletions test/e2e/onLCP-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,24 @@ describe('onLCP()', async function () {
// Wait until all images are loaded and fully rendered.
await imagesPainted();

// Load a new page to trigger the hidden state.
await navigateTo('about:blank');
await beaconCountIs(2);
const [lcp1, lcp2] = await getBeacons();

// Even though the test sets `reportAllChanges` to true, since the library
// is lazy loaded after all elements have been rendered, only a single
// change will be reported.
await beaconCountIs(1);
assertStandardReportsAreCorrect(await getBeacons());
assert(lcp1.value > 0);
assert(lcp1.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp1.name, 'LCP');
assert.strictEqual(lcp1.value, lcp1.delta);
assert.strictEqual(lcp1.rating, 'good');
assert.strictEqual(lcp1.entries.length, 1);
assert.strictEqual(lcp1.navigationType, 'navigate');

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

it('accounts for time prerendering the page', async function () {
Expand Down Expand Up @@ -332,7 +342,7 @@ describe('onLCP()', async function () {

const [lcp1] = await getBeacons();

assert(lcp1.value > 0); // Greater than the image load delay.
assert(lcp1.value > 0);
assert(lcp1.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp1.name, 'LCP');
assert.strictEqual(lcp1.value, lcp1.delta);
Expand All @@ -346,7 +356,7 @@ describe('onLCP()', async function () {

const [lcp2] = await getBeacons();

assert(lcp2.value > 0); // Greater than the image load delay.
assert(lcp2.value > 0);
assert(lcp2.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp2.name, 'LCP');
assert.strictEqual(lcp2.value, lcp2.delta);
Expand Down Expand Up @@ -377,7 +387,7 @@ describe('onLCP()', async function () {

const [lcp1] = await getBeacons();

assert(lcp1.value > 0); // Greater than the image load delay.
assert(lcp1.value > 0);
assert(lcp1.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp1.name, 'LCP');
assert.strictEqual(lcp1.value, lcp1.delta);
Expand All @@ -391,7 +401,7 @@ describe('onLCP()', async function () {

const [lcp2] = await getBeacons();

assert(lcp2.value > 0); // Greater than the image load delay.
assert(lcp2.value > 0);
assert(lcp2.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp2.name, 'LCP');
assert.strictEqual(lcp2.value, lcp2.delta);
Expand All @@ -415,7 +425,7 @@ describe('onLCP()', async function () {

const [lcp] = await getBeacons();

assert(lcp.value > 0); // Greater than the image load delay.
assert(lcp.value > 0);
assert(lcp.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp.name, 'LCP');
assert.strictEqual(lcp.value, lcp.delta);
Expand Down Expand Up @@ -654,7 +664,7 @@ describe('onLCP()', async function () {

const [lcp2] = await getBeacons();

assert(lcp2.value > 0); // Greater than the image load delay.
assert(lcp2.value > 0);
assert(lcp2.id.match(/^v4-\d+-\d+$/));
assert.strictEqual(lcp2.name, 'LCP');
assert.strictEqual(lcp2.value, lcp2.delta);
Expand Down

0 comments on commit 56e49c9

Please sign in to comment.