lighthouse 10.2.0-dev.20230509 → 10.2.0-dev.20230511
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/audits/seo/is-crawlable.d.ts +1 -0
- package/core/audits/server-response-time.js +6 -1
- package/core/computed/metrics/cumulative-layout-shift.d.ts +1 -0
- package/core/computed/metrics/cumulative-layout-shift.js +2 -1
- package/core/gather/gatherers/trace-elements.d.ts +3 -2
- package/core/gather/gatherers/trace-elements.js +10 -19
- package/dist/report/bundle.esm.js +1 -1
- package/dist/report/flow.js +1 -1
- package/dist/report/standalone.js +1 -1
- package/package.json +1 -1
- package/report/assets/templates.html +4 -0
- package/report/renderer/components.js +1 -1
- package/types/artifacts.d.ts +7 -5
- package/types/lhr/audit-details.d.ts +10 -0
- package/types/lhr/audit-result.d.ts +2 -0
|
@@ -70,11 +70,16 @@ class ServerResponseTime extends Audit {
|
|
|
70
70
|
{key: 'responseTime', valueType: 'timespanMs', label: str_(i18n.UIStrings.columnTimeSpent)},
|
|
71
71
|
];
|
|
72
72
|
|
|
73
|
+
const overallSavingsMs = Math.max(responseTime - TARGET_MS, 0);
|
|
73
74
|
const details = Audit.makeOpportunityDetails(
|
|
74
75
|
headings,
|
|
75
76
|
[{url: mainResource.url, responseTime}],
|
|
76
|
-
{overallSavingsMs
|
|
77
|
+
{overallSavingsMs}
|
|
77
78
|
);
|
|
79
|
+
details.metricSavings = {
|
|
80
|
+
FCP: overallSavingsMs,
|
|
81
|
+
LCP: overallSavingsMs,
|
|
82
|
+
};
|
|
78
83
|
|
|
79
84
|
return {
|
|
80
85
|
numericValue: responseTime,
|
|
@@ -3,6 +3,7 @@ export type LayoutShiftEvent = {
|
|
|
3
3
|
ts: number;
|
|
4
4
|
isMainFrame: boolean;
|
|
5
5
|
weightedScore: number;
|
|
6
|
+
impactedNodes?: LH.Artifacts.TraceImpactedNode[];
|
|
6
7
|
};
|
|
7
8
|
declare const CumulativeLayoutShiftComputed: typeof CumulativeLayoutShift & {
|
|
8
9
|
request: (dependencies: import("../../index.js").Trace, context: import("../../../types/utility-types.js").default.ImmutableObject<{
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
8
|
import {ProcessedTrace} from '../processed-trace.js';
|
|
9
9
|
|
|
10
|
-
/** @typedef {{ts: number, isMainFrame: boolean, weightedScore: number}} LayoutShiftEvent */
|
|
10
|
+
/** @typedef {{ts: number, isMainFrame: boolean, weightedScore: number, impactedNodes?: LH.Artifacts.TraceImpactedNode[]}} LayoutShiftEvent */
|
|
11
11
|
|
|
12
12
|
const RECENT_INPUT_WINDOW = 500;
|
|
13
13
|
|
|
@@ -65,6 +65,7 @@ class CumulativeLayoutShift {
|
|
|
65
65
|
ts: event.ts,
|
|
66
66
|
isMainFrame: event.args.data.is_main_frame,
|
|
67
67
|
weightedScore: event.args.data.weighted_score_delta,
|
|
68
|
+
impactedNodes: event.args.data.impacted_nodes,
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -21,10 +21,10 @@ declare class TraceElements extends FRGatherer {
|
|
|
21
21
|
* We calculate the score per element by taking the 'score' of each layout shift event and
|
|
22
22
|
* distributing it between all the nodes that were shifted, proportianal to the impact region of
|
|
23
23
|
* each shifted element.
|
|
24
|
-
* @param {
|
|
24
|
+
* @param {LH.Artifacts.ProcessedTrace} processedTrace
|
|
25
25
|
* @return {Array<TraceElementData>}
|
|
26
26
|
*/
|
|
27
|
-
static getTopLayoutShiftElements(
|
|
27
|
+
static getTopLayoutShiftElements(processedTrace: LH.Artifacts.ProcessedTrace): Array<TraceElementData>;
|
|
28
28
|
/**
|
|
29
29
|
* @param {LH.Trace} trace
|
|
30
30
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
@@ -80,4 +80,5 @@ declare class TraceElements extends FRGatherer {
|
|
|
80
80
|
}
|
|
81
81
|
import FRGatherer from '../base-gatherer.js';
|
|
82
82
|
import Trace from './trace.js';
|
|
83
|
+
import { ProcessedTrace } from '../../computed/processed-trace.js';
|
|
83
84
|
//# sourceMappingURL=trace-elements.d.ts.map
|
|
@@ -22,6 +22,7 @@ import {ProcessedTrace} from '../../computed/processed-trace.js';
|
|
|
22
22
|
import {ProcessedNavigation} from '../../computed/processed-navigation.js';
|
|
23
23
|
import {LighthouseError} from '../../lib/lh-error.js';
|
|
24
24
|
import {Responsiveness} from '../../computed/metrics/responsiveness.js';
|
|
25
|
+
import {CumulativeLayoutShift} from '../../computed/metrics/cumulative-layout-shift.js';
|
|
25
26
|
|
|
26
27
|
/** @typedef {{nodeId: number, score?: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[], type?: string}} TraceElementData */
|
|
27
28
|
|
|
@@ -80,34 +81,24 @@ class TraceElements extends FRGatherer {
|
|
|
80
81
|
* We calculate the score per element by taking the 'score' of each layout shift event and
|
|
81
82
|
* distributing it between all the nodes that were shifted, proportianal to the impact region of
|
|
82
83
|
* each shifted element.
|
|
83
|
-
* @param {
|
|
84
|
+
* @param {LH.Artifacts.ProcessedTrace} processedTrace
|
|
84
85
|
* @return {Array<TraceElementData>}
|
|
85
86
|
*/
|
|
86
|
-
static getTopLayoutShiftElements(
|
|
87
|
+
static getTopLayoutShiftElements(processedTrace) {
|
|
87
88
|
/** @type {Map<number, number>} */
|
|
88
89
|
const clsPerNode = new Map();
|
|
89
|
-
const shiftEvents =
|
|
90
|
-
.filter(e => e.name === 'LayoutShift')
|
|
91
|
-
.map(e => e.args?.data);
|
|
92
|
-
const indexFirstEventWithoutInput =
|
|
93
|
-
shiftEvents.findIndex(event => event && !event.had_recent_input);
|
|
94
|
-
|
|
95
|
-
shiftEvents.forEach((event, index) => {
|
|
96
|
-
if (!event || !event.impacted_nodes || !event.score) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
90
|
+
const shiftEvents = CumulativeLayoutShift.getLayoutShiftEvents(processedTrace);
|
|
99
91
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (event.had_recent_input) return;
|
|
92
|
+
shiftEvents.forEach((event) => {
|
|
93
|
+
if (!event || !event.impactedNodes) {
|
|
94
|
+
return;
|
|
104
95
|
}
|
|
105
96
|
|
|
106
97
|
let totalAreaOfImpact = 0;
|
|
107
98
|
/** @type {Map<number, number>} */
|
|
108
99
|
const pixelsMovedPerNode = new Map();
|
|
109
100
|
|
|
110
|
-
event.
|
|
101
|
+
event.impactedNodes.forEach(node => {
|
|
111
102
|
if (!node.node_id || !node.old_rect || !node.new_rect) {
|
|
112
103
|
return;
|
|
113
104
|
}
|
|
@@ -124,7 +115,7 @@ class TraceElements extends FRGatherer {
|
|
|
124
115
|
|
|
125
116
|
for (const [nodeId, pixelsMoved] of pixelsMovedPerNode.entries()) {
|
|
126
117
|
let clsContribution = clsPerNode.get(nodeId) || 0;
|
|
127
|
-
clsContribution += (pixelsMoved / totalAreaOfImpact) * event.
|
|
118
|
+
clsContribution += (pixelsMoved / totalAreaOfImpact) * event.weightedScore;
|
|
128
119
|
clsPerNode.set(nodeId, clsContribution);
|
|
129
120
|
}
|
|
130
121
|
});
|
|
@@ -272,7 +263,7 @@ class TraceElements extends FRGatherer {
|
|
|
272
263
|
const {mainThreadEvents} = processedTrace;
|
|
273
264
|
|
|
274
265
|
const lcpNodeData = await TraceElements.getLcpElement(trace, context);
|
|
275
|
-
const clsNodeData = TraceElements.getTopLayoutShiftElements(
|
|
266
|
+
const clsNodeData = TraceElements.getTopLayoutShiftElements(processedTrace);
|
|
276
267
|
const animatedElementData = await this.getAnimatedElements(mainThreadEvents);
|
|
277
268
|
const responsivenessElementData = await TraceElements.getResponsivenessElement(trace, context);
|
|
278
269
|
|
|
@@ -712,7 +712,7 @@ function createGaugePwaComponent(dom) {
|
|
|
712
712
|
function createHeadingComponent(dom) {
|
|
713
713
|
const el0 = dom.createFragment();
|
|
714
714
|
const el1 = dom.createElement("style");
|
|
715
|
-
el1.append("\n /* CSS Fireworks. Originally by Eddie Lin\n https://codepen.io/paulirish/pen/yEVMbP\n */\n .lh-pyro {\n display: none;\n z-index: 1;\n pointer-events: none;\n }\n .lh-score100 .lh-pyro {\n display: block;\n }\n .lh-score100 .lh-lighthouse stop:first-child {\n stop-color: hsla(200, 12%, 95%, 0);\n }\n .lh-score100 .lh-lighthouse stop:last-child {\n stop-color: hsla(65, 81%, 76%, 1);\n }\n\n .lh-pyro > .lh-pyro-before, .lh-pyro > .lh-pyro-after {\n position: absolute;\n width: 5px;\n height: 5px;\n border-radius: 2.5px;\n box-shadow: 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff;\n animation: 1s bang ease-out infinite backwards, 1s gravity ease-in infinite backwards, 5s position linear infinite backwards;\n animation-delay: 1s, 1s, 1s;\n }\n\n .lh-pyro > .lh-pyro-after {\n animation-delay: 2.25s, 2.25s, 2.25s;\n animation-duration: 1.25s, 1.25s, 6.25s;\n }\n\n @keyframes bang {\n to {\n box-shadow: -70px -115.67px #47ebbc, -28px -99.67px #eb47a4, 58px -31.67px #7eeb47, 13px -141.67px #eb47c5, -19px 6.33px #7347eb, -2px -74.67px #ebd247, 24px -151.67px #eb47e0, 57px -138.67px #b4eb47, -51px -104.67px #479eeb, 62px 8.33px #ebcf47, -93px 0.33px #d547eb, -16px -118.67px #47bfeb, 53px -84.67px #47eb83, 66px -57.67px #eb47bf, -93px -65.67px #91eb47, 30px -13.67px #86eb47, -2px -59.67px #83eb47, -44px 1.33px #eb47eb, 61px -58.67px #47eb73, 5px -22.67px #47e8eb, -66px -28.67px #ebe247, 42px -123.67px #eb5547, -75px 26.33px #7beb47, 15px -52.67px #a147eb, 36px -51.67px #eb8347, -38px -12.67px #eb5547, -46px -59.67px #47eb81, 78px -114.67px #eb47ba, 15px -156.67px #eb47bf, -36px 1.33px #eb4783, -72px -86.67px #eba147, 31px -46.67px #ebe247, -68px 29.33px #47e2eb, -55px 19.33px #ebe047, -56px 27.33px #4776eb, -13px -91.67px #eb5547, -47px -138.67px #47ebc7, -18px -96.67px #eb47ac, 11px -88.67px #4783eb, -67px -28.67px #47baeb, 53px 10.33px #ba47eb, 11px 19.33px #5247eb, -5px -11.67px #eb4791, -68px -4.67px #47eba7, 95px -37.67px #eb478b, -67px -162.67px #eb5d47, -54px -120.67px #eb6847, 49px -12.67px #ebe047, 88px 8.33px #47ebda, 97px 33.33px #eb8147, 6px -71.67px #ebbc47;\n }\n }\n @keyframes gravity {\n to {\n transform: translateY(80px);\n opacity: 0;\n }\n }\n @keyframes position {\n 0%, 19.9% {\n margin-top: 4%;\n margin-left: 47%;\n }\n 20%, 39.9% {\n margin-top: 7%;\n margin-left: 30%;\n }\n 40%, 59.9% {\n margin-top: 6%;\n margin-left: 70%;\n }\n 60%, 79.9% {\n margin-top: 3%;\n margin-left: 20%;\n }\n 80%, 99.9% {\n margin-top: 3%;\n margin-left: 80%;\n }\n }\n ");
|
|
715
|
+
el1.append("\n /* CSS Fireworks. Originally by Eddie Lin\n https://codepen.io/paulirish/pen/yEVMbP\n */\n .lh-pyro {\n display: none;\n z-index: 1;\n pointer-events: none;\n }\n .lh-score100 .lh-pyro {\n display: block;\n }\n .lh-score100 .lh-lighthouse stop:first-child {\n stop-color: hsla(200, 12%, 95%, 0);\n }\n .lh-score100 .lh-lighthouse stop:last-child {\n stop-color: hsla(65, 81%, 76%, 1);\n }\n\n .lh-pyro > .lh-pyro-before, .lh-pyro > .lh-pyro-after {\n position: absolute;\n width: 5px;\n height: 5px;\n border-radius: 2.5px;\n box-shadow: 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff;\n animation: 1s bang ease-out infinite backwards, 1s gravity ease-in infinite backwards, 5s position linear infinite backwards;\n animation-delay: 1s, 1s, 1s;\n }\n\n .lh-pyro > .lh-pyro-after {\n animation-delay: 2.25s, 2.25s, 2.25s;\n animation-duration: 1.25s, 1.25s, 6.25s;\n }\n\n @keyframes bang {\n to {\n opacity: 1;\n box-shadow: -70px -115.67px #47ebbc, -28px -99.67px #eb47a4, 58px -31.67px #7eeb47, 13px -141.67px #eb47c5, -19px 6.33px #7347eb, -2px -74.67px #ebd247, 24px -151.67px #eb47e0, 57px -138.67px #b4eb47, -51px -104.67px #479eeb, 62px 8.33px #ebcf47, -93px 0.33px #d547eb, -16px -118.67px #47bfeb, 53px -84.67px #47eb83, 66px -57.67px #eb47bf, -93px -65.67px #91eb47, 30px -13.67px #86eb47, -2px -59.67px #83eb47, -44px 1.33px #eb47eb, 61px -58.67px #47eb73, 5px -22.67px #47e8eb, -66px -28.67px #ebe247, 42px -123.67px #eb5547, -75px 26.33px #7beb47, 15px -52.67px #a147eb, 36px -51.67px #eb8347, -38px -12.67px #eb5547, -46px -59.67px #47eb81, 78px -114.67px #eb47ba, 15px -156.67px #eb47bf, -36px 1.33px #eb4783, -72px -86.67px #eba147, 31px -46.67px #ebe247, -68px 29.33px #47e2eb, -55px 19.33px #ebe047, -56px 27.33px #4776eb, -13px -91.67px #eb5547, -47px -138.67px #47ebc7, -18px -96.67px #eb47ac, 11px -88.67px #4783eb, -67px -28.67px #47baeb, 53px 10.33px #ba47eb, 11px 19.33px #5247eb, -5px -11.67px #eb4791, -68px -4.67px #47eba7, 95px -37.67px #eb478b, -67px -162.67px #eb5d47, -54px -120.67px #eb6847, 49px -12.67px #ebe047, 88px 8.33px #47ebda, 97px 33.33px #eb8147, 6px -71.67px #ebbc47;\n }\n }\n @keyframes gravity {\n from {\n opacity: 1;\n }\n to {\n transform: translateY(80px);\n opacity: 0;\n }\n }\n @keyframes position {\n 0%, 19.9% {\n margin-top: 4%;\n margin-left: 47%;\n }\n 20%, 39.9% {\n margin-top: 7%;\n margin-left: 30%;\n }\n 40%, 59.9% {\n margin-top: 6%;\n margin-left: 70%;\n }\n 60%, 79.9% {\n margin-top: 3%;\n margin-left: 20%;\n }\n 80%, 99.9% {\n margin-top: 3%;\n margin-left: 80%;\n }\n }\n ");
|
|
716
716
|
el0.append(el1);
|
|
717
717
|
const el2 = dom.createElement("div", "lh-header-container");
|
|
718
718
|
const el3 = dom.createElement("div", "lh-scores-wrapper-placeholder");
|