From 896399bc61273465df97332df8b0462c56e68cd8 Mon Sep 17 00:00:00 2001 From: Adriana Ixba Date: Tue, 3 Oct 2023 11:06:26 -0700 Subject: [PATCH] report: sort performance audits based on impact (#15445) --- .../__snapshots__/report-assert-test.js.snap | 8 + core/audits/audit.js | 13 +- .../byte-efficiency/uses-long-cache-ttl.js | 2 +- .../audits/metrics/cumulative-layout-shift.js | 5 +- core/audits/metrics/first-contentful-paint.js | 1 + .../metrics/largest-contentful-paint.js | 1 + core/audits/metrics/speed-index.js | 1 + core/audits/metrics/total-blocking-time.js | 1 + .../reports/sample-flow-result.json | 653 +++++++++++++++--- core/test/results/sample_v2.json | 249 +++++-- proto/lighthouse-result.proto | 36 + report/assets/styles.css | 79 +-- report/assets/templates.html | 35 - report/renderer/components.js | 53 +- .../renderer/performance-category-renderer.js | 188 +++-- .../performance-category-renderer-test.js | 278 +++++--- {core/lib => shared}/statistics.js | 0 .../lib => shared/test}/statistics-test.js | 2 +- shared/util.js | 31 + types/audit.d.ts | 4 +- types/lhr/audit-result.d.ts | 9 + 21 files changed, 1101 insertions(+), 548 deletions(-) rename {core/lib => shared}/statistics.js (100%) rename {core/test/lib => shared/test}/statistics-test.js (99%) diff --git a/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap b/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap index 1dc0c6c3d68a..3910339b0299 100644 --- a/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +++ b/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap @@ -20,6 +20,10 @@ exports[`getAssertionReport works (multiple failing) 1`] = ` \\"numericValue\\": 0.13570762803819444, \\"numericUnit\\": \\"unitless\\", \\"displayValue\\": \\"0.136\\", + \\"scoringOptions\\": { + \\"p10\\": 0.1, + \\"median\\": 0.25 + }, \\"details\\": { \\"type\\": \\"debugdata\\", \\"items\\": [ @@ -46,6 +50,10 @@ exports[`getAssertionReport works (trivial failing) 1`] = ` \\"numericValue\\": 0.13570762803819444, \\"numericUnit\\": \\"unitless\\", \\"displayValue\\": \\"0.136\\", + \\"scoringOptions\\": { + \\"p10\\": 0.1, + \\"median\\": 0.25 + }, \\"details\\": { \\"type\\": \\"debugdata\\", \\"items\\": [ diff --git a/core/audits/audit.js b/core/audits/audit.js index f6f44d65c74f..b8acb6b96ee5 100644 --- a/core/audits/audit.js +++ b/core/audits/audit.js @@ -6,7 +6,6 @@ import * as LH from '../../types/lh.js'; import {isUnderTest} from '../lib/lh-env.js'; -import * as statistics from '../lib/statistics.js'; import {Util} from '../../shared/util.js'; const DEFAULT_PASS = 'defaultPass'; @@ -105,14 +104,7 @@ class Audit { * @return {number} */ static computeLogNormalScore(controlPoints, value) { - let percentile = statistics.getLogNormalScore(controlPoints, value); - // Add a boost to scores of 90+, linearly ramping from 0 at 0.9 to half a - // point (0.005) at 1. Expands scores in (0.9, 1] to (0.9, 1.005], so more top - // scores will be a perfect 1 after the two-digit `Math.floor()` rounding below. - if (percentile > 0.9) { // getLogNormalScore ensures `percentile` can't exceed 1. - percentile += 0.05 * (percentile - 0.9); - } - return Math.floor(percentile * 100) / 100; + return Util.computeLogNormalScore(controlPoints, value); } /** @@ -411,8 +403,11 @@ class Audit { errorMessage: product.errorMessage, errorStack: product.errorStack, warnings: product.warnings, + scoringOptions: product.scoringOptions, + metricSavings: product.metricSavings, details: product.details, + guidanceLevel: audit.meta.guidanceLevel, }; } diff --git a/core/audits/byte-efficiency/uses-long-cache-ttl.js b/core/audits/byte-efficiency/uses-long-cache-ttl.js index fa3e0dd9c62a..06ea079e76b1 100644 --- a/core/audits/byte-efficiency/uses-long-cache-ttl.js +++ b/core/audits/byte-efficiency/uses-long-cache-ttl.js @@ -9,7 +9,7 @@ import parseCacheControl from 'parse-cache-control'; import {Audit} from '../audit.js'; import {NetworkRequest} from '../../lib/network-request.js'; import UrlUtils from '../../lib/url-utils.js'; -import {linearInterpolation} from '../../lib/statistics.js'; +import {linearInterpolation} from '../../../shared/statistics.js'; import * as i18n from '../../lib/i18n/i18n.js'; import {NetworkRecords} from '../../computed/network-records.js'; diff --git a/core/audits/metrics/cumulative-layout-shift.js b/core/audits/metrics/cumulative-layout-shift.js index bb503c726861..f0a2fd4fdfef 100644 --- a/core/audits/metrics/cumulative-layout-shift.js +++ b/core/audits/metrics/cumulative-layout-shift.js @@ -62,11 +62,14 @@ class CumulativeLayoutShift extends Audit { items: [rest], }; + const scoringOptions = {p10: context.options.p10, median: context.options.median}; + return { score: Audit.computeLogNormalScore( - {p10: context.options.p10, median: context.options.median}, + scoringOptions, cumulativeLayoutShift ), + scoringOptions, numericValue: cumulativeLayoutShift, numericUnit: 'unitless', displayValue: cumulativeLayoutShift.toLocaleString(context.settings.locale), diff --git a/core/audits/metrics/first-contentful-paint.js b/core/audits/metrics/first-contentful-paint.js index f1f137e702fe..8ad28a5ef29a 100644 --- a/core/audits/metrics/first-contentful-paint.js +++ b/core/audits/metrics/first-contentful-paint.js @@ -74,6 +74,7 @@ class FirstContentfulPaint extends Audit { options.scoring, metricResult.timing ), + scoringOptions: options.scoring, numericValue: metricResult.timing, numericUnit: 'millisecond', displayValue: str_(i18n.UIStrings.seconds, {timeInMs: metricResult.timing}), diff --git a/core/audits/metrics/largest-contentful-paint.js b/core/audits/metrics/largest-contentful-paint.js index 19f467a8b3f5..85ad374f0c72 100644 --- a/core/audits/metrics/largest-contentful-paint.js +++ b/core/audits/metrics/largest-contentful-paint.js @@ -83,6 +83,7 @@ class LargestContentfulPaint extends Audit { options.scoring, metricResult.timing ), + scoringOptions: options.scoring, numericValue: metricResult.timing, numericUnit: 'millisecond', displayValue: str_(i18n.UIStrings.seconds, {timeInMs: metricResult.timing}), diff --git a/core/audits/metrics/speed-index.js b/core/audits/metrics/speed-index.js index 2402db0e0915..9616bf1edb0c 100644 --- a/core/audits/metrics/speed-index.js +++ b/core/audits/metrics/speed-index.js @@ -77,6 +77,7 @@ class SpeedIndex extends Audit { options.scoring, metricResult.timing ), + scoringOptions: options.scoring, numericValue: metricResult.timing, numericUnit: 'millisecond', displayValue: str_(i18n.UIStrings.seconds, {timeInMs: metricResult.timing}), diff --git a/core/audits/metrics/total-blocking-time.js b/core/audits/metrics/total-blocking-time.js index b8fa0d8900dd..b580f10969ec 100644 --- a/core/audits/metrics/total-blocking-time.js +++ b/core/audits/metrics/total-blocking-time.js @@ -107,6 +107,7 @@ class TotalBlockingTime extends Audit { options.scoring, metricResult.timing ), + scoringOptions: options.scoring, numericValue: metricResult.timing, numericUnit: 'millisecond', displayValue: str_(i18n.UIStrings.ms, {timeInMs: metricResult.timing}), 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 041ac935be15..43ab24ddef6d 100644 --- a/core/test/fixtures/user-flows/reports/sample-flow-result.json +++ b/core/test/fixtures/user-flows/reports/sample-flow-result.json @@ -38,7 +38,11 @@ "description": "A `` not only optimizes your app for mobile screen sizes, but also prevents [a 300 millisecond delay to user input](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/). [Learn more about using the viewport meta tag](https://developer.chrome.com/docs/lighthouse/pwa/viewport/).", "score": 1, "scoreDisplayMode": "binary", - "warnings": [] + "warnings": [], + "metricSavings": { + "INP": 0 + }, + "guidanceLevel": 3 }, "first-contentful-paint": { "id": "first-contentful-paint", @@ -48,7 +52,11 @@ "scoreDisplayMode": "numeric", "numericValue": 1372.2951999999998, "numericUnit": "millisecond", - "displayValue": "1.4 s" + "displayValue": "1.4 s", + "scoringOptions": { + "p10": 1800, + "median": 3000 + } }, "largest-contentful-paint": { "id": "largest-contentful-paint", @@ -58,7 +66,11 @@ "scoreDisplayMode": "numeric", "numericValue": 1372.2951999999998, "numericUnit": "millisecond", - "displayValue": "1.4 s" + "displayValue": "1.4 s", + "scoringOptions": { + "p10": 2500, + "median": 4000 + } }, "first-meaningful-paint": { "id": "first-meaningful-paint", @@ -78,7 +90,11 @@ "scoreDisplayMode": "numeric", "numericValue": 1372.2951999999998, "numericUnit": "millisecond", - "displayValue": "1.4 s" + "displayValue": "1.4 s", + "scoringOptions": { + "p10": 3387, + "median": 5800 + } }, "screenshot-thumbnails": { "id": "screenshot-thumbnails", @@ -154,7 +170,11 @@ "scoreDisplayMode": "numeric", "numericValue": 143, "numericUnit": "millisecond", - "displayValue": "140 ms" + "displayValue": "140 ms", + "scoringOptions": { + "p10": 200, + "median": 600 + } }, "max-potential-fid": { "id": "max-potential-fid", @@ -175,6 +195,10 @@ "numericValue": 0.002631263732910156, "numericUnit": "unitless", "displayValue": "0.003", + "scoringOptions": { + "p10": 0.1, + "median": 0.25 + }, "details": { "type": "debugdata", "items": [ @@ -205,6 +229,10 @@ "numericValue": 19.687999999999988, "numericUnit": "millisecond", "displayValue": "Root document took 20 ms", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -226,7 +254,8 @@ } ], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 1 }, "interactive": { "id": "interactive", @@ -295,7 +324,8 @@ "timingType": "Mark" } ] - } + }, + "guidanceLevel": 2 }, "critical-request-chains": { "id": "critical-request-chains", @@ -322,7 +352,8 @@ "length": 1, "transferSize": 3558 } - } + }, + "guidanceLevel": 1 }, "redirects": { "id": "redirects", @@ -333,12 +364,17 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 2 }, "installable-manifest": { "id": "installable-manifest", @@ -479,6 +515,9 @@ "numericValue": 959.4240000000008, "numericUnit": "millisecond", "displayValue": "1.0 s", + "metricSavings": { + "TBT": 143 + }, "details": { "type": "table", "headings": [ @@ -529,7 +568,8 @@ "sortedBy": [ "duration" ] - } + }, + "guidanceLevel": 1 }, "bootup-time": { "id": "bootup-time", @@ -540,6 +580,9 @@ "numericValue": 288.41200000000015, "numericUnit": "millisecond", "displayValue": "0.3 s", + "metricSavings": { + "TBT": 142.50196940171634 + }, "details": { "type": "table", "headings": [ @@ -593,7 +636,8 @@ "sortedBy": [ "total" ] - } + }, + "guidanceLevel": 1 }, "uses-rel-preload": { "id": "uses-rel-preload", @@ -606,7 +650,8 @@ "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 3 }, "uses-rel-preconnect": { "id": "uses-rel-preconnect", @@ -618,6 +663,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -626,7 +675,8 @@ "sortedBy": [ "wastedMs" ] - } + }, + "guidanceLevel": 3 }, "font-display": { "id": "font-display", @@ -639,7 +689,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "diagnostics": { "id": "diagnostics", @@ -1371,6 +1422,9 @@ "score": 1, "scoreDisplayMode": "binary", "displayValue": "Third-party code blocked the main thread for 0 ms", + "metricSavings": { + "TBT": 0 + }, "details": { "type": "table", "headings": [ @@ -1435,14 +1489,19 @@ "wastedMs": 0 }, "isEntityGrouped": true - } + }, + "guidanceLevel": 1 }, "third-party-facades": { "id": "third-party-facades", "title": "Lazy load third-party resources with facades", "description": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn how to defer third-parties with a facade](https://developer.chrome.com/docs/lighthouse/performance/third-party-facades/).", "score": null, - "scoreDisplayMode": "notApplicable" + "scoreDisplayMode": "notApplicable", + "metricSavings": { + "TBT": 0 + }, + "guidanceLevel": 3 }, "largest-contentful-paint-element": { "id": "largest-contentful-paint-element", @@ -1451,6 +1510,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "1,370 ms", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "list", "items": [ @@ -1527,7 +1589,8 @@ ] } ] - } + }, + "guidanceLevel": 1 }, "lcp-lazy-loaded": { "id": "lcp-lazy-loaded", @@ -1535,6 +1598,9 @@ "description": "Above-the-fold images that are lazily loaded render later in the page lifecycle, which can delay the largest contentful paint. [Learn more about optimal lazy loading](https://web.dev/lcp-lazy-loading/).", "score": 1, "scoreDisplayMode": "binary", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "table", "headings": [ @@ -1564,7 +1630,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "layout-shift-elements": { "id": "layout-shift-elements", @@ -1573,6 +1640,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "5 elements found", + "metricSavings": { + "CLS": 0.002631263732910156 + }, "details": { "type": "table", "headings": [ @@ -1685,7 +1755,8 @@ "score": 0.00036762719987422577 } ] - } + }, + "guidanceLevel": 2 }, "long-tasks": { "id": "long-tasks", @@ -1769,7 +1840,8 @@ } ] } - } + }, + "guidanceLevel": 1 }, "no-unload-listeners": { "id": "no-unload-listeners", @@ -1784,11 +1856,15 @@ "description": "Animations which are not composited can be janky and increase CLS. [Learn how to avoid non-composited animations](https://developer.chrome.com/docs/lighthouse/performance/non-composited-animations/)", "score": null, "scoreDisplayMode": "notApplicable", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "unsized-images": { "id": "unsized-images", @@ -1796,6 +1872,9 @@ "description": "Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/optimize-cls/#images-without-dimensions)", "score": 0, "scoreDisplayMode": "binary", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [ @@ -1831,7 +1910,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "valid-source-maps": { "id": "valid-source-maps", @@ -1854,6 +1934,9 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -1876,7 +1959,8 @@ ], "pathLength": 2 } - } + }, + "guidanceLevel": 3 }, "csp-xss": { "id": "csp-xss", @@ -2700,7 +2784,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "total-byte-weight": { "id": "total-byte-weight", @@ -2770,7 +2855,8 @@ "sortedBy": [ "totalBytes" ] - } + }, + "guidanceLevel": 1 }, "offscreen-images": { "id": "offscreen-images", @@ -2782,6 +2868,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2798,7 +2888,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "render-blocking-resources": { "id": "render-blocking-resources", @@ -2808,12 +2899,17 @@ "scoreDisplayMode": "numeric", "numericValue": 0, "numericUnit": "millisecond", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 2 }, "unminified-css": { "id": "unminified-css", @@ -2824,6 +2920,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2840,7 +2940,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unminified-javascript": { "id": "unminified-javascript", @@ -2852,6 +2953,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2868,7 +2973,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unused-css-rules": { "id": "unused-css-rules", @@ -2879,6 +2985,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2895,7 +3005,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "unused-javascript": { "id": "unused-javascript", @@ -2906,6 +3017,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2922,7 +3037,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "modern-image-formats": { "id": "modern-image-formats", @@ -2934,6 +3050,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2950,7 +3070,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "uses-optimized-images": { "id": "uses-optimized-images", @@ -2962,6 +3083,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -2978,7 +3103,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "uses-text-compression": { "id": "uses-text-compression", @@ -2989,6 +3115,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -3005,7 +3135,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "uses-responsive-images": { "id": "uses-responsive-images", @@ -3016,6 +3147,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -3032,7 +3167,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "efficient-animated-content": { "id": "efficient-animated-content", @@ -3043,6 +3179,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -3059,7 +3199,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "duplicated-javascript": { "id": "duplicated-javascript", @@ -3070,6 +3211,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -3086,7 +3231,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "legacy-javascript": { "id": "legacy-javascript", @@ -3097,6 +3243,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "Potential savings of 0 KiB", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -3157,7 +3307,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "doctype": { "id": "doctype", @@ -3182,6 +3333,9 @@ "numericValue": 70, "numericUnit": "element", "displayValue": "70 elements", + "metricSavings": { + "TBT": 0 + }, "details": { "type": "table", "headings": [ @@ -3259,7 +3413,8 @@ } } ] - } + }, + "guidanceLevel": 1 }, "geolocation-on-start": { "id": "geolocation-on-start", @@ -3295,7 +3450,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "js-libraries": { "id": "js-libraries", @@ -3382,7 +3538,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "meta-description": { "id": "meta-description", @@ -3554,7 +3711,8 @@ "title": "Page didn't prevent back/forward cache restoration", "description": "Many navigations are performed by going back to a previous page, or forwards again. The back/forward cache (bfcache) can speed up these return navigations. [Learn more about the bfcache](https://developer.chrome.com/docs/lighthouse/performance/bf-cache/)", "score": 1, - "scoreDisplayMode": "binary" + "scoreDisplayMode": "binary", + "guidanceLevel": 2 } }, "configSettings": { @@ -8367,7 +8525,11 @@ "scoreDisplayMode": "numeric", "numericValue": 122.83299999999986, "numericUnit": "millisecond", - "displayValue": "120 ms" + "displayValue": "120 ms", + "scoringOptions": { + "p10": 200, + "median": 600 + } }, "cumulative-layout-shift": { "id": "cumulative-layout-shift", @@ -8378,6 +8540,10 @@ "numericValue": 0.13125, "numericUnit": "unitless", "displayValue": "0.131", + "scoringOptions": { + "p10": 0.1, + "median": 0.25 + }, "details": { "type": "debugdata", "items": [ @@ -8471,7 +8637,8 @@ "timingType": "Mark" } ] - } + }, + "guidanceLevel": 2 }, "image-aspect-ratio": { "id": "image-aspect-ratio", @@ -8648,6 +8815,9 @@ "numericValue": 867.7709999999973, "numericUnit": "millisecond", "displayValue": "0.9 s", + "metricSavings": { + "TBT": 122.83299999999986 + }, "details": { "type": "table", "headings": [ @@ -8703,7 +8873,8 @@ "sortedBy": [ "duration" ] - } + }, + "guidanceLevel": 1 }, "bootup-time": { "id": "bootup-time", @@ -8714,6 +8885,9 @@ "numericValue": 352.6489999999996, "numericUnit": "millisecond", "displayValue": "0.4 s", + "metricSavings": { + "TBT": 106.76186411159928 + }, "details": { "type": "table", "headings": [ @@ -8767,7 +8941,8 @@ "sortedBy": [ "total" ] - } + }, + "guidanceLevel": 1 }, "network-requests": { "id": "network-requests", @@ -9365,6 +9540,9 @@ "score": 1, "scoreDisplayMode": "binary", "displayValue": "Third-party code blocked the main thread for 0 ms", + "metricSavings": { + "TBT": 0 + }, "details": { "type": "table", "headings": [ @@ -9422,7 +9600,8 @@ "wastedMs": 0 }, "isEntityGrouped": true - } + }, + "guidanceLevel": 1 }, "layout-shift-elements": { "id": "layout-shift-elements", @@ -9431,6 +9610,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "1 element found", + "metricSavings": { + "CLS": 0.13125 + }, "details": { "type": "table", "headings": [ @@ -9467,7 +9649,8 @@ "score": 0.13125 } ] - } + }, + "guidanceLevel": 2 }, "long-tasks": { "id": "long-tasks", @@ -9527,7 +9710,8 @@ } ] } - } + }, + "guidanceLevel": 1 }, "no-unload-listeners": { "id": "no-unload-listeners", @@ -9542,11 +9726,15 @@ "description": "Animations which are not composited can be janky and increase CLS. [Learn how to avoid non-composited animations](https://developer.chrome.com/docs/lighthouse/performance/non-composited-animations/)", "score": null, "scoreDisplayMode": "notApplicable", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "unsized-images": { "id": "unsized-images", @@ -9554,6 +9742,9 @@ "description": "Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/optimize-cls/#images-without-dimensions)", "score": 0, "scoreDisplayMode": "binary", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [ @@ -9589,7 +9780,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "valid-source-maps": { "id": "valid-source-maps", @@ -9780,7 +9972,8 @@ "skipSumming": [ "cacheLifetimeMs" ] - } + }, + "guidanceLevel": 3 }, "total-byte-weight": { "id": "total-byte-weight", @@ -9850,7 +10043,8 @@ "sortedBy": [ "totalBytes" ] - } + }, + "guidanceLevel": 1 }, "unminified-css": { "id": "unminified-css", @@ -9861,6 +10055,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -9877,7 +10075,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unminified-javascript": { "id": "unminified-javascript", @@ -9889,6 +10088,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -9905,7 +10108,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unused-css-rules": { "id": "unused-css-rules", @@ -9916,6 +10120,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -9932,7 +10140,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "unused-javascript": { "id": "unused-javascript", @@ -9943,6 +10152,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -9959,7 +10172,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "modern-image-formats": { "id": "modern-image-formats", @@ -9971,6 +10185,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -9987,7 +10205,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "uses-optimized-images": { "id": "uses-optimized-images", @@ -9999,6 +10218,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -10015,7 +10238,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "uses-text-compression": { "id": "uses-text-compression", @@ -10026,6 +10250,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -10042,7 +10270,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "uses-responsive-images": { "id": "uses-responsive-images", @@ -10053,6 +10282,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -10069,7 +10302,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "efficient-animated-content": { "id": "efficient-animated-content", @@ -10080,6 +10314,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -10096,7 +10334,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "duplicated-javascript": { "id": "duplicated-javascript", @@ -10107,6 +10346,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -10123,7 +10366,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "legacy-javascript": { "id": "legacy-javascript", @@ -10134,6 +10378,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -10150,7 +10398,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "inspector-issues": { "id": "inspector-issues", @@ -10174,7 +10423,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "uses-passive-event-listeners": { "id": "uses-passive-event-listeners", @@ -10186,7 +10436,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "work-during-interaction": { "id": "work-during-interaction", @@ -10195,6 +10446,9 @@ "score": 1, "scoreDisplayMode": "numeric", "displayValue": "60 ms spent on event 'keypress'", + "metricSavings": { + "INP": 64 + }, "details": { "type": "list", "items": [ @@ -10376,14 +10630,16 @@ } } ] - } + }, + "guidanceLevel": 1 }, "bf-cache": { "id": "bf-cache", "title": "Page didn't prevent back/forward cache restoration", "description": "Many navigations are performed by going back to a previous page, or forwards again. The back/forward cache (bfcache) can speed up these return navigations. [Learn more about the bfcache](https://developer.chrome.com/docs/lighthouse/performance/bf-cache/)", "score": 1, - "scoreDisplayMode": "binary" + "scoreDisplayMode": "binary", + "guidanceLevel": 2 } }, "configSettings": { @@ -12160,7 +12416,11 @@ "description": "A `` not only optimizes your app for mobile screen sizes, but also prevents [a 300 millisecond delay to user input](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/). [Learn more about using the viewport meta tag](https://developer.chrome.com/docs/lighthouse/pwa/viewport/).", "score": 1, "scoreDisplayMode": "binary", - "warnings": [] + "warnings": [], + "metricSavings": { + "INP": 0 + }, + "guidanceLevel": 3 }, "image-aspect-ratio": { "id": "image-aspect-ratio", @@ -12315,6 +12575,9 @@ "description": "Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/optimize-cls/#images-without-dimensions)", "score": 0, "scoreDisplayMode": "binary", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [ @@ -12350,7 +12613,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "accesskeys": { "id": "accesskeys", @@ -14158,7 +14422,8 @@ "actualDimensions": "1000x450" } ] - } + }, + "guidanceLevel": 2 }, "doctype": { "id": "doctype", @@ -14176,6 +14441,7 @@ "numericValue": 361, "numericUnit": "element", "displayValue": "361 elements", + "metricSavings": {}, "details": { "type": "table", "headings": [ @@ -14253,7 +14519,8 @@ } } ] - } + }, + "guidanceLevel": 1 }, "js-libraries": { "id": "js-libraries", @@ -17383,7 +17650,11 @@ "description": "A `` not only optimizes your app for mobile screen sizes, but also prevents [a 300 millisecond delay to user input](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/). [Learn more about using the viewport meta tag](https://developer.chrome.com/docs/lighthouse/pwa/viewport/).", "score": 1, "scoreDisplayMode": "binary", - "warnings": [] + "warnings": [], + "metricSavings": { + "INP": 0 + }, + "guidanceLevel": 3 }, "first-contentful-paint": { "id": "first-contentful-paint", @@ -17393,7 +17664,11 @@ "scoreDisplayMode": "numeric", "numericValue": 866.7026, "numericUnit": "millisecond", - "displayValue": "0.9 s" + "displayValue": "0.9 s", + "scoringOptions": { + "p10": 1800, + "median": 3000 + } }, "largest-contentful-paint": { "id": "largest-contentful-paint", @@ -17403,7 +17678,11 @@ "scoreDisplayMode": "numeric", "numericValue": 1803.0092, "numericUnit": "millisecond", - "displayValue": "1.8 s" + "displayValue": "1.8 s", + "scoringOptions": { + "p10": 2500, + "median": 4000 + } }, "first-meaningful-paint": { "id": "first-meaningful-paint", @@ -17423,7 +17702,11 @@ "scoreDisplayMode": "numeric", "numericValue": 866.7026, "numericUnit": "millisecond", - "displayValue": "0.9 s" + "displayValue": "0.9 s", + "scoringOptions": { + "p10": 3387, + "median": 5800 + } }, "screenshot-thumbnails": { "id": "screenshot-thumbnails", @@ -17499,7 +17782,11 @@ "scoreDisplayMode": "numeric", "numericValue": 13, "numericUnit": "millisecond", - "displayValue": "10 ms" + "displayValue": "10 ms", + "scoringOptions": { + "p10": 200, + "median": 600 + } }, "max-potential-fid": { "id": "max-potential-fid", @@ -17520,6 +17807,10 @@ "numericValue": 0, "numericUnit": "unitless", "displayValue": "0", + "scoringOptions": { + "p10": 0.1, + "median": 0.25 + }, "details": { "type": "debugdata", "items": [ @@ -17550,6 +17841,10 @@ "numericValue": 10.263, "numericUnit": "millisecond", "displayValue": "Root document took 10 ms", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -17571,7 +17866,8 @@ } ], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 1 }, "interactive": { "id": "interactive", @@ -17640,7 +17936,8 @@ "timingType": "Mark" } ] - } + }, + "guidanceLevel": 2 }, "critical-request-chains": { "id": "critical-request-chains", @@ -17667,7 +17964,8 @@ "length": 1, "transferSize": 3596 } - } + }, + "guidanceLevel": 1 }, "redirects": { "id": "redirects", @@ -17678,12 +17976,17 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 2 }, "installable-manifest": { "id": "installable-manifest", @@ -17824,6 +18127,9 @@ "numericValue": 454.39200000000045, "numericUnit": "millisecond", "displayValue": "0.5 s", + "metricSavings": { + "TBT": 13 + }, "details": { "type": "table", "headings": [ @@ -17874,7 +18180,8 @@ "sortedBy": [ "duration" ] - } + }, + "guidanceLevel": 1 }, "bootup-time": { "id": "bootup-time", @@ -17885,6 +18192,9 @@ "numericValue": 169.10399999999998, "numericUnit": "millisecond", "displayValue": "0.2 s", + "metricSavings": { + "TBT": 25.85177364864864 + }, "details": { "type": "table", "headings": [ @@ -17944,7 +18254,8 @@ "sortedBy": [ "total" ] - } + }, + "guidanceLevel": 1 }, "uses-rel-preload": { "id": "uses-rel-preload", @@ -17957,7 +18268,8 @@ "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 3 }, "uses-rel-preconnect": { "id": "uses-rel-preconnect", @@ -17969,6 +18281,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -17977,7 +18293,8 @@ "sortedBy": [ "wastedMs" ] - } + }, + "guidanceLevel": 3 }, "font-display": { "id": "font-display", @@ -17990,7 +18307,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "diagnostics": { "id": "diagnostics", @@ -18680,6 +18998,9 @@ "score": 1, "scoreDisplayMode": "binary", "displayValue": "Third-party code blocked the main thread for 0 ms", + "metricSavings": { + "TBT": 0 + }, "details": { "type": "table", "headings": [ @@ -18725,14 +19046,19 @@ } ], "isEntityGrouped": true - } + }, + "guidanceLevel": 1 }, "third-party-facades": { "id": "third-party-facades", "title": "Lazy load third-party resources with facades", "description": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn how to defer third-parties with a facade](https://developer.chrome.com/docs/lighthouse/performance/third-party-facades/).", "score": null, - "scoreDisplayMode": "notApplicable" + "scoreDisplayMode": "notApplicable", + "metricSavings": { + "TBT": 0 + }, + "guidanceLevel": 3 }, "largest-contentful-paint-element": { "id": "largest-contentful-paint-element", @@ -18741,6 +19067,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "1,800 ms", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "list", "items": [ @@ -18817,7 +19146,8 @@ ] } ] - } + }, + "guidanceLevel": 1 }, "lcp-lazy-loaded": { "id": "lcp-lazy-loaded", @@ -18825,6 +19155,9 @@ "description": "Above-the-fold images that are lazily loaded render later in the page lifecycle, which can delay the largest contentful paint. [Learn more about optimal lazy loading](https://web.dev/lcp-lazy-loading/).", "score": 1, "scoreDisplayMode": "binary", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "table", "headings": [ @@ -18854,7 +19187,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "layout-shift-elements": { "id": "layout-shift-elements", @@ -18862,11 +19196,15 @@ "description": "These DOM elements contribute most to the CLS of the page. [Learn how to improve CLS](https://web.dev/optimize-cls/)", "score": null, "scoreDisplayMode": "notApplicable", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "long-tasks": { "id": "long-tasks", @@ -18937,7 +19275,8 @@ } ] } - } + }, + "guidanceLevel": 1 }, "no-unload-listeners": { "id": "no-unload-listeners", @@ -18952,11 +19291,15 @@ "description": "Animations which are not composited can be janky and increase CLS. [Learn how to avoid non-composited animations](https://developer.chrome.com/docs/lighthouse/performance/non-composited-animations/)", "score": null, "scoreDisplayMode": "notApplicable", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "unsized-images": { "id": "unsized-images", @@ -18964,6 +19307,9 @@ "description": "Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/optimize-cls/#images-without-dimensions)", "score": 0, "scoreDisplayMode": "binary", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [ @@ -19018,7 +19364,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "valid-source-maps": { "id": "valid-source-maps", @@ -19041,6 +19388,9 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -19063,7 +19413,8 @@ ], "pathLength": 2 } - } + }, + "guidanceLevel": 3 }, "csp-xss": { "id": "csp-xss", @@ -19924,7 +20275,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "total-byte-weight": { "id": "total-byte-weight", @@ -19974,7 +20326,8 @@ "sortedBy": [ "totalBytes" ] - } + }, + "guidanceLevel": 1 }, "offscreen-images": { "id": "offscreen-images", @@ -19986,6 +20339,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20002,7 +20359,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "render-blocking-resources": { "id": "render-blocking-resources", @@ -20012,12 +20370,17 @@ "scoreDisplayMode": "numeric", "numericValue": 0, "numericUnit": "millisecond", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 2 }, "unminified-css": { "id": "unminified-css", @@ -20028,6 +20391,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20044,7 +20411,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unminified-javascript": { "id": "unminified-javascript", @@ -20056,6 +20424,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20072,7 +20444,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unused-css-rules": { "id": "unused-css-rules", @@ -20083,6 +20456,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20099,7 +20476,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "unused-javascript": { "id": "unused-javascript", @@ -20110,6 +20488,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20126,7 +20508,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "modern-image-formats": { "id": "modern-image-formats", @@ -20138,6 +20521,10 @@ "numericUnit": "millisecond", "displayValue": "Potential savings of 67 KiB", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 330 + }, "details": { "type": "opportunity", "headings": [ @@ -20200,7 +20587,8 @@ "LCP": 330 } } - } + }, + "guidanceLevel": 3 }, "uses-optimized-images": { "id": "uses-optimized-images", @@ -20212,6 +20600,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20228,7 +20620,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "uses-text-compression": { "id": "uses-text-compression", @@ -20239,6 +20632,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20255,7 +20652,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "uses-responsive-images": { "id": "uses-responsive-images", @@ -20266,6 +20664,10 @@ "numericValue": 300, "numericUnit": "millisecond", "displayValue": "Potential savings of 51 KiB", + "metricSavings": { + "FCP": 0, + "LCP": 300 + }, "details": { "type": "opportunity", "headings": [ @@ -20326,7 +20728,8 @@ "LCP": 300 } } - } + }, + "guidanceLevel": 2 }, "efficient-animated-content": { "id": "efficient-animated-content", @@ -20337,6 +20740,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20353,7 +20760,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "duplicated-javascript": { "id": "duplicated-javascript", @@ -20364,6 +20772,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -20380,7 +20792,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "legacy-javascript": { "id": "legacy-javascript", @@ -20391,6 +20804,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -20451,7 +20868,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "doctype": { "id": "doctype", @@ -20476,6 +20894,9 @@ "numericValue": 81, "numericUnit": "element", "displayValue": "81 elements", + "metricSavings": { + "TBT": 0 + }, "details": { "type": "table", "headings": [ @@ -20553,7 +20974,8 @@ } } ] - } + }, + "guidanceLevel": 1 }, "geolocation-on-start": { "id": "geolocation-on-start", @@ -20589,7 +21011,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 2 }, "js-libraries": { "id": "js-libraries", @@ -20676,7 +21099,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "meta-description": { "id": "meta-description", @@ -20905,7 +21329,8 @@ "title": "Page didn't prevent back/forward cache restoration", "description": "Many navigations are performed by going back to a previous page, or forwards again. The back/forward cache (bfcache) can speed up these return navigations. [Learn more about the bfcache](https://developer.chrome.com/docs/lighthouse/performance/bf-cache/)", "score": 1, - "scoreDisplayMode": "binary" + "scoreDisplayMode": "binary", + "guidanceLevel": 2 } }, "configSettings": { diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index b89188daf7b6..01dac7b23c55 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -52,7 +52,11 @@ "description": "A `` not only optimizes your app for mobile screen sizes, but also prevents [a 300 millisecond delay to user input](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/). [Learn more about using the viewport meta tag](https://developer.chrome.com/docs/lighthouse/pwa/viewport/).", "score": 1, "scoreDisplayMode": "binary", - "warnings": [] + "warnings": [], + "metricSavings": { + "INP": 0 + }, + "guidanceLevel": 3 }, "first-contentful-paint": { "id": "first-contentful-paint", @@ -62,7 +66,11 @@ "scoreDisplayMode": "numeric", "numericValue": 6843.95, "numericUnit": "millisecond", - "displayValue": "6.8 s" + "displayValue": "6.8 s", + "scoringOptions": { + "p10": 1800, + "median": 3000 + } }, "largest-contentful-paint": { "id": "largest-contentful-paint", @@ -72,7 +80,11 @@ "scoreDisplayMode": "numeric", "numericValue": 13319.961, "numericUnit": "millisecond", - "displayValue": "13.3 s" + "displayValue": "13.3 s", + "scoringOptions": { + "p10": 2500, + "median": 4000 + } }, "first-meaningful-paint": { "id": "first-meaningful-paint", @@ -92,7 +104,11 @@ "scoreDisplayMode": "numeric", "numericValue": 8114, "numericUnit": "millisecond", - "displayValue": "8.1 s" + "displayValue": "8.1 s", + "scoringOptions": { + "p10": 3387, + "median": 5800 + } }, "screenshot-thumbnails": { "id": "screenshot-thumbnails", @@ -168,7 +184,11 @@ "scoreDisplayMode": "numeric", "numericValue": 1220.691999999999, "numericUnit": "millisecond", - "displayValue": "1,220 ms" + "displayValue": "1,220 ms", + "scoringOptions": { + "p10": 200, + "median": 600 + } }, "max-potential-fid": { "id": "max-potential-fid", @@ -189,6 +209,10 @@ "numericValue": 0.13570762803819444, "numericUnit": "unitless", "displayValue": "0.136", + "scoringOptions": { + "p10": 0.1, + "median": 0.25 + }, "details": { "type": "debugdata", "items": [ @@ -308,6 +332,10 @@ "numericValue": 568.468, "numericUnit": "millisecond", "displayValue": "Root document took 570 ms", + "metricSavings": { + "FCP": 468.46799999999996, + "LCP": 468.46799999999996 + }, "details": { "type": "opportunity", "headings": [ @@ -329,7 +357,8 @@ } ], "overallSavingsMs": 468.46799999999996 - } + }, + "guidanceLevel": 1 }, "interactive": { "id": "interactive", @@ -607,7 +636,8 @@ "timingType": "Mark" } ] - } + }, + "guidanceLevel": 2 }, "critical-request-chains": { "id": "critical-request-chains", @@ -744,7 +774,8 @@ "length": 2, "transferSize": 903 } - } + }, + "guidanceLevel": 1 }, "redirects": { "id": "redirects", @@ -755,12 +786,17 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 2 }, "installable-manifest": { "id": "installable-manifest", @@ -1000,6 +1036,9 @@ "numericValue": 2240.732999999998, "numericUnit": "millisecond", "displayValue": "2.2 s", + "metricSavings": { + "TBT": 1220.691999999999 + }, "details": { "type": "table", "headings": [ @@ -1050,7 +1089,8 @@ "sortedBy": [ "duration" ] - } + }, + "guidanceLevel": 1 }, "bootup-time": { "id": "bootup-time", @@ -1061,6 +1101,9 @@ "numericValue": 1324.3129999999999, "numericUnit": "millisecond", "displayValue": "1.3 s", + "metricSavings": { + "TBT": 1209.4020894768312 + }, "details": { "type": "table", "headings": [ @@ -1114,7 +1157,8 @@ "sortedBy": [ "total" ] - } + }, + "guidanceLevel": 1 }, "uses-rel-preload": { "id": "uses-rel-preload", @@ -1127,7 +1171,8 @@ "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 3 }, "uses-rel-preconnect": { "id": "uses-rel-preconnect", @@ -1139,6 +1184,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -1147,7 +1196,8 @@ "sortedBy": [ "wastedMs" ] - } + }, + "guidanceLevel": 3 }, "font-display": { "id": "font-display", @@ -1160,7 +1210,8 @@ "type": "table", "headings": [], "items": [] - } + }, + "guidanceLevel": 3 }, "diagnostics": { "id": "diagnostics", @@ -2145,6 +2196,9 @@ "score": 1, "scoreDisplayMode": "binary", "displayValue": "Third-party code blocked the main thread for 0 ms", + "metricSavings": { + "TBT": 23.424291876693196 + }, "details": { "type": "table", "headings": [ @@ -2202,14 +2256,19 @@ "wastedMs": 0 }, "isEntityGrouped": true - } + }, + "guidanceLevel": 1 }, "third-party-facades": { "id": "third-party-facades", "title": "Lazy load third-party resources with facades", "description": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn how to defer third-parties with a facade](https://developer.chrome.com/docs/lighthouse/performance/third-party-facades/).", "score": null, - "scoreDisplayMode": "notApplicable" + "scoreDisplayMode": "notApplicable", + "metricSavings": { + "TBT": 0 + }, + "guidanceLevel": 3 }, "largest-contentful-paint-element": { "id": "largest-contentful-paint-element", @@ -2218,6 +2277,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "13,320 ms", + "metricSavings": { + "LCP": 10819.961 + }, "details": { "type": "list", "items": [ @@ -2294,14 +2356,19 @@ ] } ] - } + }, + "guidanceLevel": 1 }, "lcp-lazy-loaded": { "id": "lcp-lazy-loaded", "title": "Largest Contentful Paint image was not lazily loaded", "description": "Above-the-fold images that are lazily loaded render later in the page lifecycle, which can delay the largest contentful paint. [Learn more about optimal lazy loading](https://web.dev/lcp-lazy-loading/).", "score": null, - "scoreDisplayMode": "notApplicable" + "scoreDisplayMode": "notApplicable", + "metricSavings": { + "LCP": 0 + }, + "guidanceLevel": 3 }, "layout-shift-elements": { "id": "layout-shift-elements", @@ -2310,6 +2377,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "5 elements found", + "metricSavings": { + "CLS": 0.13570762803819444 + }, "details": { "type": "table", "headings": [ @@ -2422,7 +2492,8 @@ "score": 0.004071364067636093 } ] - } + }, + "guidanceLevel": 2 }, "long-tasks": { "id": "long-tasks", @@ -2499,7 +2570,8 @@ } ] } - } + }, + "guidanceLevel": 1 }, "no-unload-listeners": { "id": "no-unload-listeners", @@ -2536,6 +2608,9 @@ "score": null, "scoreDisplayMode": "informative", "displayValue": "1 animated element found", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [ @@ -2587,7 +2662,8 @@ } } ] - } + }, + "guidanceLevel": 2 }, "unsized-images": { "id": "unsized-images", @@ -2595,6 +2671,9 @@ "description": "Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/optimize-cls/#images-without-dimensions)", "score": 0, "scoreDisplayMode": "binary", + "metricSavings": { + "CLS": 0 + }, "details": { "type": "table", "headings": [ @@ -2649,7 +2728,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "valid-source-maps": { "id": "valid-source-maps", @@ -2672,6 +2752,9 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -2739,7 +2822,8 @@ ], "pathLength": 4 } - } + }, + "guidanceLevel": 3 }, "csp-xss": { "id": "csp-xss", @@ -4151,7 +4235,8 @@ "skipSumming": [ "cacheLifetimeMs" ] - } + }, + "guidanceLevel": 3 }, "total-byte-weight": { "id": "total-byte-weight", @@ -4221,7 +4306,8 @@ "sortedBy": [ "totalBytes" ] - } + }, + "guidanceLevel": 1 }, "offscreen-images": { "id": "offscreen-images", @@ -4233,6 +4319,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -4249,7 +4339,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "render-blocking-resources": { "id": "render-blocking-resources", @@ -4260,6 +4351,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "Potential savings of 0 ms", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -4312,7 +4407,8 @@ } ], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 2 }, "unminified-css": { "id": "unminified-css", @@ -4323,6 +4419,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -4339,7 +4439,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 3 }, "unminified-javascript": { "id": "unminified-javascript", @@ -4351,6 +4452,10 @@ "numericUnit": "millisecond", "displayValue": "Potential savings of 82 KiB", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 300 + }, "details": { "type": "opportunity", "headings": [ @@ -4390,7 +4495,8 @@ "LCP": 300 } } - } + }, + "guidanceLevel": 3 }, "unused-css-rules": { "id": "unused-css-rules", @@ -4401,6 +4507,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -4417,7 +4527,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "unused-javascript": { "id": "unused-javascript", @@ -4428,6 +4539,10 @@ "numericValue": 750, "numericUnit": "millisecond", "displayValue": "Potential savings of 64 KiB", + "metricSavings": { + "FCP": 0, + "LCP": 450 + }, "details": { "type": "opportunity", "headings": [ @@ -4483,7 +4598,8 @@ "LCP": 450 } } - } + }, + "guidanceLevel": 2 }, "modern-image-formats": { "id": "modern-image-formats", @@ -4495,6 +4611,10 @@ "numericUnit": "millisecond", "displayValue": "Potential savings of 76 KiB", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 450 + }, "details": { "type": "opportunity", "headings": [ @@ -4597,7 +4717,8 @@ "LCP": 450 } } - } + }, + "guidanceLevel": 3 }, "uses-optimized-images": { "id": "uses-optimized-images", @@ -4609,6 +4730,10 @@ "numericUnit": "millisecond", "displayValue": "", "warnings": [], + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -4625,7 +4750,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "uses-text-compression": { "id": "uses-text-compression", @@ -4636,6 +4762,10 @@ "numericValue": 2400, "numericUnit": "millisecond", "displayValue": "Potential savings of 143 KiB", + "metricSavings": { + "FCP": 150, + "LCP": 750 + }, "details": { "type": "opportunity", "headings": [ @@ -4679,7 +4809,8 @@ "LCP": 750 } } - } + }, + "guidanceLevel": 3 }, "uses-responsive-images": { "id": "uses-responsive-images", @@ -4690,6 +4821,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -4706,7 +4841,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "efficient-animated-content": { "id": "efficient-animated-content", @@ -4717,6 +4853,10 @@ "numericValue": 3450, "numericUnit": "millisecond", "displayValue": "Potential savings of 666 KiB", + "metricSavings": { + "FCP": 0, + "LCP": 3300 + }, "details": { "type": "opportunity", "headings": [ @@ -4755,7 +4895,8 @@ "LCP": 3300 } } - } + }, + "guidanceLevel": 3 }, "duplicated-javascript": { "id": "duplicated-javascript", @@ -4766,6 +4907,10 @@ "numericValue": 0, "numericUnit": "millisecond", "displayValue": "", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [], @@ -4782,7 +4927,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "legacy-javascript": { "id": "legacy-javascript", @@ -4793,6 +4939,10 @@ "numericValue": 450, "numericUnit": "millisecond", "displayValue": "Potential savings of 26 KiB", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, "details": { "type": "opportunity", "headings": [ @@ -4863,7 +5013,8 @@ "LCP": 0 } } - } + }, + "guidanceLevel": 2 }, "doctype": { "id": "doctype", @@ -4888,6 +5039,9 @@ "numericValue": 153, "numericUnit": "element", "displayValue": "153 elements", + "metricSavings": { + "TBT": 1 + }, "details": { "type": "table", "headings": [ @@ -4965,7 +5119,8 @@ } } ] - } + }, + "guidanceLevel": 1 }, "geolocation-on-start": { "id": "geolocation-on-start", @@ -5060,7 +5215,8 @@ } } ] - } + }, + "guidanceLevel": 2 }, "js-libraries": { "id": "js-libraries", @@ -5202,12 +5358,17 @@ "scoreDisplayMode": "numeric", "numericValue": 0, "numericUnit": "millisecond", + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, "details": { "type": "opportunity", "headings": [], "items": [], "overallSavingsMs": 0 - } + }, + "guidanceLevel": 3 }, "uses-passive-event-listeners": { "id": "uses-passive-event-listeners", @@ -5235,7 +5396,8 @@ } } ] - } + }, + "guidanceLevel": 3 }, "meta-description": { "id": "meta-description", @@ -5543,7 +5705,8 @@ "protocolReason": "BrowsingInstanceNotSwapped" } ] - } + }, + "guidanceLevel": 2 } }, "configSettings": { diff --git a/proto/lighthouse-result.proto b/proto/lighthouse-result.proto index d9080282df11..6f5dc7c2af2e 100644 --- a/proto/lighthouse-result.proto +++ b/proto/lighthouse-result.proto @@ -382,6 +382,42 @@ message AuditResult { // Stacktrace of error, if any occurred while processing the audit. string errorStack = 13; + + // Message containing the audit's MetricSavings. + message MetricSavings { + // Optional numeric value representing the audit's savings for the LCP metric. + optional google.protobuf.DoubleValue LCP = 1; + + // Optional numeric value representing the audit's savings for the FCP metric. + optional google.protobuf.DoubleValue FCP = 2; + + // Optional numeric value representing the audit's savings for the CLS metric. + optional google.protobuf.DoubleValue CLS = 3; + + // Optional numeric value representing the audit's savings for the TBT metric. + optional google.protobuf.DoubleValue TBT = 4; + + // Optional numeric value representing the audit's savings for the INP metric. + optional google.protobuf.DoubleValue INP = 5; + } + + // The audit's MetricSavings. + MetricSavings metricSavings = 14; + + // Message containing ScoringOptions. + message ScoringOptions { + // Scoring option's p10. + google.protobuf.DoubleValue p10 = 1; + + // Scoring option's median. + google.protobuf.DoubleValue median = 2; + } + + // The audit's ScoringOption. + ScoringOptions scoringOptions = 15; + + // An audit's guidance level. + google.protobuf.DoubleValue guidanceLevel = 16; } // Message containing the i18n data for the LHR - Version 1 diff --git a/report/assets/styles.css b/report/assets/styles.css index b9dbc4c883a1..770e0b7b3b8d 100644 --- a/report/assets/styles.css +++ b/report/assets/styles.css @@ -131,7 +131,6 @@ --section-padding-vertical: calc(var(--default-padding) * 6); --snippet-background-color: var(--color-gray-50); --snippet-color: #0938C2; - --sparkline-height: 5px; --stackpack-padding-horizontal: 10px; --sticky-header-background-color: var(--report-background-color); --sticky-header-buffer: calc(var(--topbar-height) + var(--sticky-header-height)); @@ -238,11 +237,6 @@ --topbar-height: 28px; --topbar-logo-size: 20px; } - - /* Not enough space to adequately show the relative savings bars. */ - .lh-sparkline { - display: none; - } } .lh-vars.lh-devtools { @@ -611,7 +605,6 @@ .lh-audit__display-text, -.lh-load-opportunity__sparkline, .lh-chevron-container { margin: 0 var(--audit-margin-horizontal); } @@ -628,14 +621,11 @@ font-size: var(--report-monospace-font-size); } -/* Prepend display text with em dash separator. But not in Opportunities. */ +/* Prepend display text with em dash separator. */ .lh-audit__display-text:not(:empty):before { content: '—'; margin-right: var(--audit-margin-horizontal); } -.lh-audit-group.lh-audit-group--load-opportunities .lh-audit__display-text:not(:empty):before { - display: none; -} /* Expandable Details (Audit Groups, Audits) */ .lh-audit__header { @@ -644,10 +634,6 @@ padding: var(--default-padding); } -.lh-audit--load-opportunity .lh-audit__header { - display: block; -} - .lh-metricfilter { display: grid; @@ -875,68 +861,6 @@ color: var(--color-fail-secondary); } -/* Perf load opportunity */ - -.lh-load-opportunity__cols { - display: flex; - align-items: flex-start; -} - -.lh-load-opportunity__header .lh-load-opportunity__col { - color: var(--color-gray-600); - display: unset; - line-height: calc(2.3 * var(--report-font-size)); -} - -.lh-load-opportunity__col { - display: flex; -} - -.lh-load-opportunity__col--one { - flex: 5; - align-items: center; - margin-right: 2px; -} -.lh-load-opportunity__col--two { - flex: 4; - text-align: right; -} - -.lh-audit--load-opportunity .lh-audit__display-text { - text-align: right; - flex: 0 0 7.5ch; -} - - -/* Sparkline */ - -.lh-load-opportunity__sparkline { - flex: 1; - margin-top: calc((var(--report-line-height) - var(--sparkline-height)) / 2); -} - -.lh-sparkline { - height: var(--sparkline-height); - width: 100%; -} - -.lh-sparkline__bar { - height: 100%; - float: right; -} - -.lh-audit--pass .lh-sparkline__bar { - background: var(--color-pass); -} - -.lh-audit--average .lh-sparkline__bar { - background: var(--color-average); -} - -.lh-audit--fail .lh-sparkline__bar { - background: var(--color-fail); -} - /* Filmstrip */ .lh-filmstrip-container { @@ -1078,7 +1002,6 @@ .lh-details, .lh-category-header__description, -.lh-load-opportunity__header, .lh-audit-group__footer { font-size: var(--report-font-size-secondary); line-height: var(--report-line-height-secondary); diff --git a/report/assets/templates.html b/report/assets/templates.html index 0a8a5acc5764..9972999d9b5f 100644 --- a/report/assets/templates.html +++ b/report/assets/templates.html @@ -94,41 +94,6 @@ - - - - - -