From 729afdc68cfd72e7b5112a9529fec65d357cf836 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:10:21 -0700 Subject: [PATCH] core(largest-contentful-paint-element): add LCP savings (#15178) --- .../largest-contentful-paint-element.js | 25 ++++++++++++++++--- .../largest-contentful-paint-element-test.js | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/core/audits/largest-contentful-paint-element.js b/core/audits/largest-contentful-paint-element.js index 7eecaa9441c7..24a1367abbc0 100644 --- a/core/audits/largest-contentful-paint-element.js +++ b/core/audits/largest-contentful-paint-element.js @@ -8,7 +8,8 @@ import log from 'lighthouse-logger'; import {Audit} from './audit.js'; import * as i18n from '../lib/i18n/i18n.js'; -import {LargestContentfulPaint} from '../computed/metrics/largest-contentful-paint.js'; +import {LargestContentfulPaint as LargestContentfulPaintComputed} from '../computed/metrics/largest-contentful-paint.js'; +import LargestContentfulPaint from './metrics/largest-contentful-paint.js'; import {LCPBreakdown} from '../computed/metrics/lcp-breakdown.js'; import {Sentry} from '../lib/sentry.js'; @@ -124,14 +125,22 @@ class LargestContentfulPaintElement extends Audit { settings: context.settings, URL: artifacts.URL}; const elementTable = this.makeElementTable(artifacts); - if (!elementTable) return {score: null, notApplicable: true}; + if (!elementTable) { + return { + score: null, + notApplicable: true, + metricSavings: {LCP: 0}, + }; + } const items = [elementTable]; let displayValue; + let metricLcp = 0; try { - const {timing: metricLcp} = - await LargestContentfulPaint.request(metricComputationData, context); + const lcpResult = + await LargestContentfulPaintComputed.request(metricComputationData, context); + metricLcp = lcpResult.timing; displayValue = str_(i18n.UIStrings.ms, {timeInMs: metricLcp}); const phaseTable = await this.makePhaseTable(metricLcp, metricComputationData, context); @@ -146,10 +155,18 @@ class LargestContentfulPaintElement extends Audit { const details = Audit.makeListDetails(items); + // Conceptually, this doesn't make much sense as "savings" for this audit since there isn't anything to "fix". + // However, this audit will always be useful when improving LCP and that should be reflected in our impact calculations. + const idealLcp = LargestContentfulPaint.defaultOptions[context.settings.formFactor].scoring.p10; + const lcpSavings = Math.max(0, metricLcp - idealLcp); + return { score: 1, displayValue, details, + metricSavings: { + LCP: lcpSavings, + }, }; } } diff --git a/core/test/audits/largest-contentful-paint-element-test.js b/core/test/audits/largest-contentful-paint-element-test.js index a058eedb759f..63bb3b870d03 100644 --- a/core/test/audits/largest-contentful-paint-element-test.js +++ b/core/test/audits/largest-contentful-paint-element-test.js @@ -103,6 +103,7 @@ describe('Performance: largest-contentful-paint-element audit', () => { expect(auditResult.score).toEqual(1); expect(auditResult.notApplicable).toBeUndefined(); expect(auditResult.displayValue).toBeDisplayString('5,800\xa0ms'); + expect(auditResult.metricSavings).toEqual({LCP: 3304}); // 5804 - 2500 (p10 mobile) expect(auditResult.details.items).toHaveLength(2); expect(auditResult.details.items[0].items).toHaveLength(1); expect(auditResult.details.items[0].items[0].node.path).toEqual('1,HTML,3,BODY,5,DIV,0,HEADER'); @@ -148,6 +149,7 @@ describe('Performance: largest-contentful-paint-element audit', () => { expect(auditResult.score).toEqual(null); expect(auditResult.notApplicable).toEqual(true); expect(auditResult.displayValue).toBeUndefined(); + expect(auditResult.metricSavings).toEqual({LCP: 0}); expect(auditResult.details).toBeUndefined(); });