From 79b8907ef438d9b34d1296556d67e565e680bc51 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Mon, 1 Apr 2024 11:44:26 -0700 Subject: [PATCH] core: deprecate `overallSavingsMs` (#15902) --- .../test-definitions/byte-efficiency.js | 4 +- .../byte-efficiency/byte-efficiency-audit.js | 39 +--------- .../byte-efficiency/offscreen-images.js | 15 ---- core/audits/dobetterweb/uses-http2.js | 36 +--------- .../byte-efficiency-audit-test.js | 71 +------------------ .../duplicated-javascript-test.js | 2 +- .../reports/sample-flow-result.json | 4 +- core/test/results/sample_v2.json | 24 +++---- flow-report/src/summary/category.tsx | 22 +++--- flow-report/test/summary/category-test.tsx | 8 ++- types/lhr/audit-details.d.ts | 13 ++-- 11 files changed, 47 insertions(+), 191 deletions(-) diff --git a/cli/test/smokehouse/test-definitions/byte-efficiency.js b/cli/test/smokehouse/test-definitions/byte-efficiency.js index ae62437cf9f4..b712396d96a6 100644 --- a/cli/test/smokehouse/test-definitions/byte-efficiency.js +++ b/cli/test/smokehouse/test-definitions/byte-efficiency.js @@ -115,7 +115,7 @@ const expectations = { details: { // the specific ms value is not meaningful for this smoketest // *some largish amount* of savings should be reported - overallSavingsMs: '>500', + overallSavingsMs: '>100', overallSavingsBytes: '>45000', items: [ { @@ -218,7 +218,7 @@ const expectations = { details: { // the specific ms value is not meaningful for this smoketest // *some largish amount* of savings should be reported - overallSavingsMs: '>700', + overallSavingsMs: '>100', overallSavingsBytes: '>50000', items: { length: 3, diff --git a/core/audits/byte-efficiency/byte-efficiency-audit.js b/core/audits/byte-efficiency/byte-efficiency-audit.js index b11909fc0734..22fbde1286f3 100644 --- a/core/audits/byte-efficiency/byte-efficiency-audit.js +++ b/core/audits/byte-efficiency/byte-efficiency-audit.js @@ -5,11 +5,9 @@ */ import {Audit} from '../audit.js'; -import {LanternInteractive} from '../../computed/metrics/lantern-interactive.js'; import * as i18n from '../../lib/i18n/i18n.js'; import {NetworkRecords} from '../../computed/network-records.js'; import {LoadSimulator} from '../../computed/load-simulator.js'; -import {PageDependencyGraph} from '../../computed/page-dependency-graph.js'; import {LanternLargestContentfulPaint} from '../../computed/metrics/lantern-largest-contentful-paint.js'; import {LanternFirstContentfulPaint} from '../../computed/metrics/lantern-first-contentful-paint.js'; import {LCPImageRecord} from '../../computed/lcp-image-record.js'; @@ -151,37 +149,6 @@ class ByteEfficiencyAudit extends Audit { }; } - /** - * Computes the estimated effect of all the byte savings on the maximum of the following: - * - * - end time of the last long task in the provided graph - * - (if includeLoad is true or not provided) end time of the last node in the graph - * - * @param {Array} results The array of byte savings results per resource - * @param {Node} graph - * @param {Simulator} simulator - * @param {{includeLoad?: boolean, providedWastedBytesByUrl?: Map}=} options - * @return {number} - */ - static computeWasteWithTTIGraph(results, graph, simulator, options) { - options = Object.assign({includeLoad: true}, options); - const {savings: savingsOnOverallLoad, simulationBeforeChanges, simulationAfterChanges} = - this.computeWasteWithGraph(results, graph, simulator, { - ...options, - label: 'overallLoad', - }); - - const savingsOnTTI = - LanternInteractive.getLastLongTaskEndTime(simulationBeforeChanges.nodeTimings) - - LanternInteractive.getLastLongTaskEndTime(simulationAfterChanges.nodeTimings); - - let savings = savingsOnTTI; - if (options.includeLoad) savings = Math.max(savings, savingsOnOverallLoad); - - // Round waste to nearest 10ms - return Math.round(Math.max(savings, 0) / 10) * 10; - } - /** * @param {ByteEfficiencyProduct} result * @param {Simulator} simulator @@ -204,7 +171,6 @@ class ByteEfficiencyAudit extends Audit { // This is useful information in the LHR and should be preserved. let wastedMs; if (metricComputationInput.gatherContext.gatherMode === 'navigation') { - const graph = await PageDependencyGraph.request(metricComputationInput, context); const { optimisticGraph: optimisticFCPGraph, } = await LanternFirstContentfulPaint.request(metricComputationInput, context); @@ -212,10 +178,6 @@ class ByteEfficiencyAudit extends Audit { optimisticGraph: optimisticLCPGraph, } = await LanternLargestContentfulPaint.request(metricComputationInput, context); - wastedMs = this.computeWasteWithTTIGraph(results, graph, simulator, { - providedWastedBytesByUrl: result.wastedBytesByUrl, - }); - const {savings: fcpSavings} = this.computeWasteWithGraph( results, optimisticFCPGraph, @@ -243,6 +205,7 @@ class ByteEfficiencyAudit extends Audit { metricSavings.FCP = fcpSavings; metricSavings.LCP = Math.max(lcpGraphSavings, lcpRecordSavings); + wastedMs = metricSavings.LCP; } else { wastedMs = simulator.computeWastedMsFromWastedBytes(wastedBytes); } diff --git a/core/audits/byte-efficiency/offscreen-images.js b/core/audits/byte-efficiency/offscreen-images.js index 8acb5edd7890..2e88b7e29b76 100644 --- a/core/audits/byte-efficiency/offscreen-images.js +++ b/core/audits/byte-efficiency/offscreen-images.js @@ -156,21 +156,6 @@ class OffscreenImages extends ByteEfficiencyAudit { }); } - /** - * The default byte efficiency audit will report max(TTI, load), since lazy-loading offscreen - * images won't reduce the overall time and the wasted bytes are really only "wasted" for TTI, - * override the function to just look at TTI savings. - * - * @param {Array} results - * @param {LH.Gatherer.Simulation.GraphNode} graph - * @param {LH.Gatherer.Simulation.Simulator} simulator - * @return {number} - */ - static computeWasteWithTTIGraph(results, graph, simulator) { - return super.computeWasteWithTTIGraph(results, graph, simulator, - {includeLoad: false}); - } - /** * @param {LH.Artifacts} artifacts * @param {Array} networkRecords diff --git a/core/audits/dobetterweb/uses-http2.js b/core/audits/dobetterweb/uses-http2.js index 231fad1f514c..0c22639b81be 100644 --- a/core/audits/dobetterweb/uses-http2.js +++ b/core/audits/dobetterweb/uses-http2.js @@ -15,11 +15,9 @@ import {Audit} from '../audit.js'; import {EntityClassification} from '../../computed/entity-classification.js'; import UrlUtils from '../../lib/url-utils.js'; -import {LanternInteractive} from '../../computed/metrics/lantern-interactive.js'; import {NetworkRequest} from '../../lib/network-request.js'; import {NetworkRecords} from '../../computed/network-records.js'; import {LoadSimulator} from '../../computed/load-simulator.js'; -import {PageDependencyGraph} from '../../computed/page-dependency-graph.js'; import {LanternLargestContentfulPaint} from '../../computed/metrics/lantern-largest-contentful-paint.js'; import {LanternFirstContentfulPaint} from '../../computed/metrics/lantern-first-contentful-paint.js'; import * as i18n from '../../lib/i18n/i18n.js'; @@ -117,32 +115,6 @@ class UsesHTTP2Audit extends Audit { }; } - /** - * Computes the estimated effect all results being converted to use http/2, the max of: - * - * - end time of the last long task in the provided graph - * - end time of the last node in the graph - * @param {Array<{url: string}>} results - * @param {Node} graph - * @param {Simulator} simulator - * @return {number} - */ - static computeWasteWithTTIGraph(results, graph, simulator) { - const {savings: savingsOnOverallLoad, simulationBefore, simulationAfter} = - this.computeWasteWithGraph(results, graph, simulator, { - label: 'tti', - }); - - const savingsOnTTI = - LanternInteractive.getLastLongTaskEndTime(simulationBefore.nodeTimings) - - LanternInteractive.getLastLongTaskEndTime(simulationAfter.nodeTimings); - - const savings = Math.max(savingsOnTTI, savingsOnOverallLoad); - - // Round waste to nearest 10ms - return Math.round(Math.max(savings, 0) / 10) * 10; - } - /** * Determines whether a network request is a "static resource" that would benefit from H2 multiplexing. * XHRs, tracking pixels, etc generally don't benefit as much because they aren't requested en-masse @@ -235,7 +207,6 @@ class UsesHTTP2Audit extends Audit { * @return {Promise} */ static async audit(artifacts, context) { - const trace = artifacts.traces[Audit.DEFAULT_PASS]; const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; const URL = artifacts.URL; const networkRecords = await NetworkRecords.request(devtoolsLog, context); @@ -269,7 +240,6 @@ class UsesHTTP2Audit extends Audit { devtoolsLog, settings, }; - const pageGraph = await PageDependencyGraph.request({trace, devtoolsLog, URL}, context); const simulator = await LoadSimulator.request(simulatorOptions, context); const metricComputationInput = Audit.makeMetricComputationDataInput(artifacts, context); @@ -280,8 +250,6 @@ class UsesHTTP2Audit extends Audit { pessimisticGraph: lcpGraph, } = await LanternLargestContentfulPaint.request(metricComputationInput, context); - const wastedMsTti = UsesHTTP2Audit.computeWasteWithTTIGraph( - resources, pageGraph, simulator); const wasteFcp = UsesHTTP2Audit.computeWasteWithGraph(resources, fcpGraph, simulator, {label: 'fcp'}); @@ -296,11 +264,11 @@ class UsesHTTP2Audit extends Audit { ]; const details = Audit.makeOpportunityDetails(headings, resources, - {overallSavingsMs: wastedMsTti}); + {overallSavingsMs: wasteLcp.savings}); return { displayValue, - numericValue: wastedMsTti, + numericValue: wasteLcp.savings, numericUnit: 'millisecond', score: resources.length ? 0 : 1, details, diff --git a/core/test/audits/byte-efficiency/byte-efficiency-audit-test.js b/core/test/audits/byte-efficiency/byte-efficiency-audit-test.js index c03db3c5183f..381494bd8aab 100644 --- a/core/test/audits/byte-efficiency/byte-efficiency-audit-test.js +++ b/core/test/audits/byte-efficiency/byte-efficiency-audit-test.js @@ -228,7 +228,7 @@ describe('Byte efficiency base audit', () => { {computedCache: new Map()} ); - assert.equal(result.numericValue, 300); + assert.equal(result.numericValue, 0); }); it('should create load simulator with the specified settings', async () => { @@ -255,78 +255,13 @@ describe('Byte efficiency base audit', () => { let result = await MockAudit.audit(artifacts, {settings, computedCache}); // expect modest savings expect(result.numericValue).toBeLessThan(5000); - expect(result.numericValue).toMatchInlineSnapshot(`4640`); + expect(result.numericValue).toMatchInlineSnapshot(`440`); settings = {throttlingMethod: 'simulate', throttling: ultraSlowThrottling}; result = await MockAudit.audit(artifacts, {settings, computedCache}); // expect lots of savings expect(result.numericValue).not.toBeLessThan(5000); - expect(result.numericValue).toMatchInlineSnapshot(`55730`); - }); - - it('should compute TTI savings differently from load savings', async () => { - class MockAudit extends ByteEfficiencyAudit { - static audit_(artifacts, records) { - return { - items: records.map(record => ({url: record.url, wastedBytes: record.transferSize * 0.5})), - headings: [], - }; - } - } - - class MockTtiAudit extends MockAudit { - static computeWasteWithTTIGraph(results, graph, simulator) { - return ByteEfficiencyAudit.computeWasteWithTTIGraph(results, graph, simulator, - {includeLoad: false}); - } - } - - const artifacts = { - GatherContext: {gatherMode: 'navigation'}, - traces: {defaultPass: trace}, - devtoolsLogs: {defaultPass: devtoolsLog}, - URL: getURLArtifactFromDevtoolsLog(devtoolsLog), - }; - const computedCache = new Map(); - - const modestThrottling = {rttMs: 150, throughputKbps: 1000, cpuSlowdownMultiplier: 2}; - const settings = {throttlingMethod: 'simulate', throttling: modestThrottling}; - const result = await MockAudit.audit(artifacts, {settings, computedCache}); - const resultTti = await MockTtiAudit.audit(artifacts, {settings, computedCache}); - expect(resultTti.numericValue).toBeLessThan(result.numericValue); - expect(result.numericValue).toMatchInlineSnapshot(`2130`); - expect(resultTti.numericValue).toMatchInlineSnapshot(`110`); - }); - - it('should allow overriding of computeWasteWithTTIGraph', async () => { - class MockAudit extends ByteEfficiencyAudit { - static audit_(artifacts, records) { - return { - items: records.map(record => ({url: record.url, wastedBytes: record.transferSize * 0.5})), - headings: [], - }; - } - } - - class MockOverrideAudit extends MockAudit { - static computeWasteWithTTIGraph(results, graph, simulator) { - return 0.5 * ByteEfficiencyAudit.computeWasteWithTTIGraph(results, graph, simulator); - } - } - - const artifacts = { - GatherContext: {gatherMode: 'navigation'}, - traces: {defaultPass: trace}, - devtoolsLogs: {defaultPass: devtoolsLog}, - URL: getURLArtifactFromDevtoolsLog(devtoolsLog), - }; - const computedCache = new Map(); - - const modestThrottling = {rttMs: 150, throughputKbps: 1000, cpuSlowdownMultiplier: 2}; - const settings = {throttlingMethod: 'simulate', throttling: modestThrottling}; - const result = await MockAudit.audit(artifacts, {settings, computedCache}); - const resultOverride = await MockOverrideAudit.audit(artifacts, {settings, computedCache}); - expect(resultOverride.numericValue).toEqual(result.numericValue * 0.5); + expect(result.numericValue).toMatchInlineSnapshot(`5790`); }); it('should compute savings with throughput in timespan mode', async () => { diff --git a/core/test/audits/byte-efficiency/duplicated-javascript-test.js b/core/test/audits/byte-efficiency/duplicated-javascript-test.js index 455c4a0f1b6b..58ff8d83819f 100644 --- a/core/test/audits/byte-efficiency/duplicated-javascript-test.js +++ b/core/test/audits/byte-efficiency/duplicated-javascript-test.js @@ -366,7 +366,7 @@ describe('DuplicatedJavascript computed artifact', () => { const results = await DuplicatedJavascript.audit(artifacts, context); // Without the `wastedBytesByUrl` this would be zero because the items don't define a url. - expect(results.details.overallSavingsMs).toBe(1680); + expect(results.details.overallSavingsMs).toBe(1370); }); it('_getNodeModuleName', () => { diff --git a/core/test/fixtures/user-flows/reports/sample-flow-result.json b/core/test/fixtures/user-flows/reports/sample-flow-result.json index 0ae30ea12406..ae01fbf2752b 100644 --- a/core/test/fixtures/user-flows/reports/sample-flow-result.json +++ b/core/test/fixtures/user-flows/reports/sample-flow-result.json @@ -20912,7 +20912,7 @@ "description": "Image formats like WebP and AVIF often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more about modern image formats](https://developer.chrome.com/docs/lighthouse/performance/uses-webp-images/).", "score": 0, "scoreDisplayMode": "metricSavings", - "numericValue": 300, + "numericValue": 330, "numericUnit": "millisecond", "displayValue": "Potential savings of 67 KiB", "warnings": [], @@ -20970,7 +20970,7 @@ "wastedWebpBytes": 65184 } ], - "overallSavingsMs": 300, + "overallSavingsMs": 330, "overallSavingsBytes": 68889.75, "sortedBy": [ "wastedBytes" diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index 77752a1e9429..5b220a4a6213 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -4545,7 +4545,7 @@ "description": "Minifying JavaScript files can reduce payload sizes and script parse time. [Learn how to minify JavaScript](https://developer.chrome.com/docs/lighthouse/performance/unminified-javascript/).", "score": 0, "scoreDisplayMode": "metricSavings", - "numericValue": 1200, + "numericValue": 630, "numericUnit": "millisecond", "displayValue": "Potential savings of 81 KiB", "warnings": [], @@ -4580,7 +4580,7 @@ "wastedPercent": 50.176166426166425 } ], - "overallSavingsMs": 1200, + "overallSavingsMs": 630, "overallSavingsBytes": 83453, "sortedBy": [ "wastedBytes" @@ -4633,7 +4633,7 @@ "description": "Reduce unused JavaScript and defer loading scripts until they are required to decrease bytes consumed by network activity. [Learn how to reduce unused JavaScript](https://developer.chrome.com/docs/lighthouse/performance/unused-javascript/).", "score": 0, "scoreDisplayMode": "metricSavings", - "numericValue": 750, + "numericValue": 330, "numericUnit": "millisecond", "displayValue": "Potential savings of 63 KiB", "metricSavings": { @@ -4683,7 +4683,7 @@ "wastedPercent": 70.99531129443884 } ], - "overallSavingsMs": 750, + "overallSavingsMs": 330, "overallSavingsBytes": 64572, "sortedBy": [ "wastedBytes" @@ -4704,7 +4704,7 @@ "description": "Image formats like WebP and AVIF often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more about modern image formats](https://developer.chrome.com/docs/lighthouse/performance/uses-webp-images/).", "score": 0, "scoreDisplayMode": "metricSavings", - "numericValue": 450, + "numericValue": 330, "numericUnit": "millisecond", "displayValue": "Potential savings of 76 KiB", "warnings": [], @@ -4802,7 +4802,7 @@ "wastedWebpBytes": 9002 } ], - "overallSavingsMs": 450, + "overallSavingsMs": 330, "overallSavingsBytes": 77874.3, "sortedBy": [ "wastedBytes" @@ -4856,7 +4856,7 @@ "description": "Text-based resources should be served with compression (gzip, deflate or brotli) to minimize total network bytes. [Learn more about text compression](https://developer.chrome.com/docs/lighthouse/performance/uses-text-compression/).", "score": 0, "scoreDisplayMode": "metricSavings", - "numericValue": 2400, + "numericValue": 930, "numericUnit": "millisecond", "displayValue": "Potential savings of 143 KiB", "metricSavings": { @@ -4894,7 +4894,7 @@ "wastedBytes": 11647 } ], - "overallSavingsMs": 2400, + "overallSavingsMs": 930, "overallSavingsBytes": 146478, "sortedBy": [ "wastedBytes" @@ -4947,7 +4947,7 @@ "description": "Large GIFs are inefficient for delivering animated content. Consider using MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save network bytes. [Learn more about efficient video formats](https://developer.chrome.com/docs/lighthouse/performance/efficient-animated-content/)", "score": 0.5, "scoreDisplayMode": "metricSavings", - "numericValue": 3300, + "numericValue": 0, "numericUnit": "millisecond", "displayValue": "Potential savings of 666 KiB", "metricSavings": { @@ -4980,7 +4980,7 @@ "wastedBytes": 682028 } ], - "overallSavingsMs": 3300, + "overallSavingsMs": 0, "overallSavingsBytes": 682028, "sortedBy": [ "wastedBytes" @@ -5033,7 +5033,7 @@ "description": "Polyfills and transforms enable legacy browsers to use new JavaScript features. However, many aren't necessary for modern browsers. For your bundled JavaScript, adopt a modern script deployment strategy using module/nomodule feature detection to reduce the amount of code shipped to modern browsers, while retaining support for legacy browsers. [Learn how to use modern JavaScript](https://web.dev/articles/publish-modern-javascript)", "score": 0, "scoreDisplayMode": "metricSavings", - "numericValue": 450, + "numericValue": 300, "numericUnit": "millisecond", "displayValue": "Potential savings of 26 KiB", "metricSavings": { @@ -5098,7 +5098,7 @@ "totalBytes": 0 } ], - "overallSavingsMs": 450, + "overallSavingsMs": 300, "overallSavingsBytes": 26585, "sortedBy": [ "wastedBytes" diff --git a/flow-report/src/summary/category.tsx b/flow-report/src/summary/category.tsx index 8cc4c31175b3..c4c1ecee2216 100644 --- a/flow-report/src/summary/category.tsx +++ b/flow-report/src/summary/category.tsx @@ -39,13 +39,6 @@ function getScoreToBeGained(audit: ScoredAuditRef): number { return audit.weight * (1 - audit.result.score); } -function getOverallSavings(audit: LH.ReportResult.AuditRef): number { - return ( - audit.result.details && - audit.result.details.overallSavingsMs - ) || 0; -} - const SummaryTooltipAudit: FunctionComponent<{audit: LH.ReportResult.AuditRef}> = ({audit}) => { const rating = ReportUtils.calculateRating(audit.result.score, audit.result.scoreDisplayMode); return ( @@ -63,10 +56,10 @@ const SummaryTooltipAudits: FunctionComponent<{category: LH.ReportResult.Categor return audit.result.score !== null && // Metrics should not be displayed in this group. audit.group !== 'metrics' && - // Audits in performance group "hidden" should not be counted. - (audit.group !== 'hidden' || category.id !== 'performance') && - // We don't want unweighted audits except for opportunities with potential savings. - (audit.weight > 0 || getOverallSavings(audit) > 0) && + // Audits in group "hidden" should not be counted. + audit.group !== 'hidden' && + // We don't want unweighted audits except for performance diagnostics. + (audit.weight > 0 || audit.group === 'diagnostics') && // Passing audits should never be high impact. !ReportUtils.showAsPassed(audit.result); } @@ -79,7 +72,12 @@ const SummaryTooltipAudits: FunctionComponent<{category: LH.ReportResult.Categor const remainingScoreA = getScoreToBeGained(a); const remainingScoreB = getScoreToBeGained(b); if (remainingScoreA !== remainingScoreB) return remainingScoreB - remainingScoreA; - return getOverallSavings(b) - getOverallSavings(a); + if (a.result.score !== b.result.score) return a.result.score - b.result.score; + + // TODO: Sort using overall impact from metric savings, not just LCP + const aLcpSavings = a.result.metricSavings?.LCP || 0; + const bLcpSavings = b.result.metricSavings?.LCP || 0; + return bLcpSavings - aLcpSavings; }) .splice(0, MAX_TOOLTIP_AUDITS); if (!audits.length) return null; diff --git a/flow-report/test/summary/category-test.tsx b/flow-report/test/summary/category-test.tsx index b4774a24ab8a..f8799024f7b1 100644 --- a/flow-report/test/summary/category-test.tsx +++ b/flow-report/test/summary/category-test.tsx @@ -136,6 +136,7 @@ describe('SummaryTooltip', () => { {result: {score: 0, scoreDisplayMode: 'binary', title: 'Audit 1'}, weight: 1, group: 'group'}, {result: {score: 0, scoreDisplayMode: 'binary', title: 'Audit 2'}, weight: 2, group: 'group'}, {result: {score: 0, scoreDisplayMode: 'binary', title: 'Audit 3'}, weight: 3, group: 'group'}, + {result: {score: 0, scoreDisplayMode: 'binary', title: 'Audit 4'}, weight: 0, group: 'group'}, /* eslint-enable max-len */ ], }; @@ -161,9 +162,10 @@ describe('SummaryTooltip', () => { auditRefs: [ /* eslint-disable max-len */ {result: {score: 0.75, scoreDisplayMode: 'numeric', title: 'Metric 1'}, weight: 1, group: 'metrics'}, - {result: {score: 0, scoreDisplayMode: 'numeric', title: 'Audit 1', details: {type: 'opportunity', overallSavingsMs: 500}}, weight: 0, group: 'opportunities'}, - {result: {score: 0, scoreDisplayMode: 'numeric', title: 'Audit 2', details: {type: 'opportunity', overallSavingsMs: 1000}}, weight: 0, group: 'opportunities'}, - {result: {score: 0, scoreDisplayMode: 'numeric', title: 'Audit 3', details: {type: 'opportunity', overallSavingsMs: 100}}, weight: 0, group: 'opportunities'}, + {result: {score: 0, scoreDisplayMode: 'numeric', title: 'Audit 1', metricSavings: {LCP: 500}}, weight: 0, group: 'diagnostics'}, + {result: {score: 0, scoreDisplayMode: 'numeric', title: 'Audit 2', metricSavings: {LCP: 1000}}, weight: 0, group: 'diagnostics'}, + {result: {score: 0, scoreDisplayMode: 'numeric', title: 'Audit 3', metricSavings: {LCP: 100, FCP: 10_000}}, weight: 0, group: 'diagnostics'}, + {result: {score: 0.5, scoreDisplayMode: 'numeric', title: 'Audit 4', metricSavings: {LCP: 10_000}}, weight: 0, group: 'diagnostics'}, /* eslint-enable max-len */ ], }; diff --git a/types/lhr/audit-details.d.ts b/types/lhr/audit-details.d.ts index a8f012105b9a..8d62b005f686 100644 --- a/types/lhr/audit-details.d.ts +++ b/types/lhr/audit-details.d.ts @@ -9,10 +9,6 @@ import Treemap from './treemap.js'; /** Common properties for all details types. */ interface BaseDetails { - /** If present and audit is part of the performance category, audit is treated as an Opportunity. */ - overallSavingsMs?: number; - /** Optional additional Opportunity information. */ - overallSavingsBytes?: number; /** Additional information, usually used for including debug or meta information in the LHR */ debugData?: Details.DebugData; } @@ -85,6 +81,15 @@ declare module Details { isEntityGrouped?: boolean; /** Column keys to skip summing. If omitted, all column types supported are summed. */ skipSumming?: Array; + /** + * @deprecated + * Historically this represents the time saved on the entire page load. It's mostly used as an + * alias for `metricSavings.LCP` now. We recommend using `metricSavings` directly for more + * metric-specific savings estimates. + */ + overallSavingsMs?: number; + /** Total byte savings covered by this audit. */ + overallSavingsBytes?: number; } interface Screenshot extends BaseDetails {