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.
@@ -6,6 +6,7 @@ declare class IsCrawlable extends Audit {
6
6
  static handleMetaElement(metaElement: LH.Artifacts.MetaElement): {
7
7
  source: {
8
8
  snippet: string;
9
+ /** @type {Array<string|undefined>} */
9
10
  type: "node";
10
11
  lhId?: string | undefined;
11
12
  path?: string | undefined;
@@ -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: responseTime - TARGET_MS}
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 {Array<LH.TraceEvent>} mainThreadEvents
24
+ * @param {LH.Artifacts.ProcessedTrace} processedTrace
25
25
  * @return {Array<TraceElementData>}
26
26
  */
27
- static getTopLayoutShiftElements(mainThreadEvents: Array<LH.TraceEvent>): Array<TraceElementData>;
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 {Array<LH.TraceEvent>} mainThreadEvents
84
+ * @param {LH.Artifacts.ProcessedTrace} processedTrace
84
85
  * @return {Array<TraceElementData>}
85
86
  */
86
- static getTopLayoutShiftElements(mainThreadEvents) {
87
+ static getTopLayoutShiftElements(processedTrace) {
87
88
  /** @type {Map<number, number>} */
88
89
  const clsPerNode = new Map();
89
- const shiftEvents = mainThreadEvents
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
- // Ignore events with input, unless it's one of the initial events.
101
- // See comment in computed/metrics/cumulative-layout-shift.js.
102
- if (indexFirstEventWithoutInput !== -1 && index >= indexFirstEventWithoutInput) {
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.impacted_nodes.forEach(node => {
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.score;
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(mainThreadEvents);
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");