From 65050eef36b6ee3898bc525c59979b25770317f7 Mon Sep 17 00:00:00 2001 From: Philip Walton Date: Sat, 23 Apr 2022 19:16:59 -0700 Subject: [PATCH] Only include last LCP entry in metric entries --- README.md | 7 ++++--- src/getLCP.ts | 31 +++++++++++++++---------------- test/e2e/getLCP-test.js | 5 +++-- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a0e9112b..deaba16f 100644 --- a/README.md +++ b/README.md @@ -550,9 +550,10 @@ interface Metric { // together and calculate a total. id: string; - // Any performance entries used in the metric value calculation. - // Note, entries will be added to the array as the value changes. - entries: (PerformanceEntry | FirstInputPolyfillEntry | NavigationTimingPolyfillEntry)[]; + // Any performance entries relevant to the metric value calculation. + // The array may also be empty if the metric value was not based on any + // entries (e.g. a CLS value of 0 given no layout shifts). + entries: (PerformanceEntry | LayoutShift | FirstInputPolyfillEntry | NavigationTimingPolyfillEntry)[]; } ``` diff --git a/src/getLCP.ts b/src/getLCP.ts index c64b9a63..4b2de307 100644 --- a/src/getLCP.ts +++ b/src/getLCP.ts @@ -30,32 +30,31 @@ export const getLCP = (onReport: ReportHandler, reportAllChanges?: boolean) => { let metric = initMetric('LCP'); let report: ReturnType; - const entryHandler = (entry: PerformanceEntry) => { - // The startTime attribute returns the value of the renderTime if it is not 0, - // and the value of the loadTime otherwise. - const value = entry.startTime; + const handleEntries = (entries: Metric['entries']) => { + const lastEntry = entries[entries.length - 1]; + if (lastEntry) { + // The startTime attribute returns the value of the renderTime if it is + // not 0, and the value of the loadTime otherwise. + const value = lastEntry.startTime; - // If the page was hidden prior to paint time of the entry, - // ignore it and mark the metric as final, otherwise add the entry. - if (value < visibilityWatcher.firstHiddenTime) { - metric.value = value; - metric.entries.push(entry); - report(); + // If the page was hidden prior to paint time of the entry, + // ignore it and mark the metric as final, otherwise add the entry. + if (value < visibilityWatcher.firstHiddenTime) { + metric.value = value; + metric.entries = [lastEntry]; + report(); + } } }; - const entriesHandler = (entries: Metric['entries']) => { - entries.forEach(entryHandler); - }; - - const po = observe('largest-contentful-paint', entriesHandler); + const po = observe('largest-contentful-paint', handleEntries); if (po) { report = bindReporter(onReport, metric, reportAllChanges); const stopListening = () => { if (!reportedMetricIDs[metric.id]) { - entriesHandler(po.takeRecords()); + handleEntries(po.takeRecords()); po.disconnect(); reportedMetricIDs[metric.id] = true; report(true); diff --git a/test/e2e/getLCP-test.js b/test/e2e/getLCP-test.js index 6c7dafb3..8d876101 100644 --- a/test/e2e/getLCP-test.js +++ b/test/e2e/getLCP-test.js @@ -233,7 +233,7 @@ const assertStandardReportsAreCorrect = (beacons) => { assert(lcp.id.match(/^v2-\d+-\d+$/)); assert.strictEqual(lcp.name, 'LCP'); assert.strictEqual(lcp.value, lcp.delta); - assert.strictEqual(lcp.entries.length, 2); + assert.strictEqual(lcp.entries.length, 1); }; const assertFullReportsAreCorrect = (beacons) => { @@ -249,5 +249,6 @@ const assertFullReportsAreCorrect = (beacons) => { assert.strictEqual(lcp2.value, lcp1.value + lcp2.delta); assert.strictEqual(lcp2.name, 'LCP'); assert.strictEqual(lcp2.id, lcp1.id); - assert.strictEqual(lcp2.entries.length, 2); + assert.strictEqual(lcp2.entries.length, 1); + assert(lcp2.entries[0].startTime > lcp1.entries[0].startTime); };