lighthouse 9.5.0-dev.20230125 → 9.5.0-dev.20230127

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.
@@ -222,7 +222,6 @@ class LegacyJavascript extends ByteEfficiencyAudit {
222
222
  ['String.fromCodePoint', 'es6.string.from-code-point'],
223
223
  ['String.raw', 'es6.string.raw'],
224
224
  ['String.prototype.repeat', 'es6.string.repeat'],
225
- ['Array.prototype.includes', 'es7.array.includes'],
226
225
  ['Object.entries', 'es7.object.entries'],
227
226
  ['Object.getOwnPropertyDescriptors', 'es7.object.get-own-property-descriptors'],
228
227
  ['Object.values', 'es7.object.values'],
@@ -266,7 +265,7 @@ class LegacyJavascript extends ByteEfficiencyAudit {
266
265
  },
267
266
  {
268
267
  name: '@babel/plugin-transform-regenerator',
269
- expression: /regeneratorRuntime\.a?wrap/.source,
268
+ expression: /regeneratorRuntime\(?\)?\.a?wrap/.source,
270
269
  // Example of this transform: https://gist.github.com/connorjclark/af8bccfff377ac44efc104a79bc75da2
271
270
  // `regeneratorRuntime.awrap` is generated for every usage of `await`, and adds ~80 bytes each.
272
271
  estimateBytes: result => result.count * 80,
@@ -27,14 +27,22 @@ declare class PreloadLCPImageAudit extends Audit {
27
27
  /**
28
28
  * @param {LH.Artifacts.NetworkRequest} mainResource
29
29
  * @param {LH.Gatherer.Simulation.GraphNode} graph
30
- * @param {LH.Artifacts.TraceElement} lcpElement
31
- * @param {Array<LH.Artifacts.ImageElement>} imageElements
30
+ * @param {string | undefined} lcpUrl
32
31
  * @return {{lcpNodeToPreload?: LH.Gatherer.Simulation.GraphNetworkNode, initiatorPath?: InitiatorPath}}
33
32
  */
34
- static getLCPNodeToPreload(mainResource: LH.Artifacts.NetworkRequest, graph: LH.Gatherer.Simulation.GraphNode, lcpElement: LH.Artifacts.TraceElement, imageElements: Array<LH.Artifacts.ImageElement>): {
33
+ static getLCPNodeToPreload(mainResource: LH.Artifacts.NetworkRequest, graph: LH.Gatherer.Simulation.GraphNode, lcpUrl: string | undefined): {
35
34
  lcpNodeToPreload?: import("../lib/dependency-graph/network-node.js").NetworkNode | undefined;
36
35
  initiatorPath?: InitiatorPath | undefined;
37
36
  };
37
+ /**
38
+ * Match the LCP event with the paint event to get the URL of the image actually painted.
39
+ * This could differ from the `ImageElement` associated with the nodeId if e.g. the LCP
40
+ * was a pseudo-element associated with a node containing a smaller background-image.
41
+ * @param {LH.Trace} trace
42
+ * @param {LH.Artifacts.ProcessedNavigation} processedNavigation
43
+ * @return {string | undefined}
44
+ */
45
+ static getLcpUrl(trace: LH.Trace, processedNavigation: LH.Artifacts.ProcessedNavigation): string | undefined;
38
46
  /**
39
47
  * Computes the estimated effect of preloading the LCP image.
40
48
  * @param {LH.Artifacts.TraceElement} lcpElement
@@ -64,4 +72,5 @@ export namespace UIStrings {
64
72
  }
65
73
  import { Audit } from "./audit.js";
66
74
  import { NetworkRequest } from "../lib/network-request.js";
75
+ import { ProcessedNavigation } from "../computed/processed-navigation.js";
67
76
  //# sourceMappingURL=preload-lcp-image.d.ts.map
@@ -11,6 +11,7 @@ import {MainResource} from '../computed/main-resource.js';
11
11
  import {LanternLargestContentfulPaint} from '../computed/metrics/lantern-largest-contentful-paint.js';
12
12
  import {LoadSimulator} from '../computed/load-simulator.js';
13
13
  import {ByteEfficiencyAudit} from './byte-efficiency/byte-efficiency-audit.js';
14
+ import {ProcessedNavigation} from '../computed/processed-navigation.js';
14
15
 
15
16
  const UIStrings = {
16
17
  /** Title of a lighthouse audit that tells a user to preload an image in order to improve their LCP time. */
@@ -36,8 +37,7 @@ class PreloadLCPImageAudit extends Audit {
36
37
  title: str_(UIStrings.title),
37
38
  description: str_(UIStrings.description),
38
39
  supportedModes: ['navigation'],
39
- requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'TraceElements',
40
- 'ImageElements'],
40
+ requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'TraceElements'],
41
41
  scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
42
42
  };
43
43
  }
@@ -87,17 +87,11 @@ class PreloadLCPImageAudit extends Audit {
87
87
  /**
88
88
  * @param {LH.Artifacts.NetworkRequest} mainResource
89
89
  * @param {LH.Gatherer.Simulation.GraphNode} graph
90
- * @param {LH.Artifacts.TraceElement} lcpElement
91
- * @param {Array<LH.Artifacts.ImageElement>} imageElements
90
+ * @param {string | undefined} lcpUrl
92
91
  * @return {{lcpNodeToPreload?: LH.Gatherer.Simulation.GraphNetworkNode, initiatorPath?: InitiatorPath}}
93
92
  */
94
- static getLCPNodeToPreload(mainResource, graph, lcpElement, imageElements) {
95
- const lcpImageElement = imageElements.find(elem => {
96
- return elem.node.devtoolsNodePath === lcpElement.node.devtoolsNodePath;
97
- });
98
-
99
- if (!lcpImageElement) return {};
100
- const lcpUrl = lcpImageElement.src;
93
+ static getLCPNodeToPreload(mainResource, graph, lcpUrl) {
94
+ if (!lcpUrl) return {};
101
95
  const {lcpNode, path} = PreloadLCPImageAudit.findLCPNode(graph, lcpUrl);
102
96
  if (!lcpNode || !path) return {};
103
97
 
@@ -116,6 +110,29 @@ class PreloadLCPImageAudit extends Audit {
116
110
  };
117
111
  }
118
112
 
113
+ /**
114
+ * Match the LCP event with the paint event to get the URL of the image actually painted.
115
+ * This could differ from the `ImageElement` associated with the nodeId if e.g. the LCP
116
+ * was a pseudo-element associated with a node containing a smaller background-image.
117
+ * @param {LH.Trace} trace
118
+ * @param {LH.Artifacts.ProcessedNavigation} processedNavigation
119
+ * @return {string | undefined}
120
+ */
121
+ static getLcpUrl(trace, processedNavigation) {
122
+ const lcpEvent = processedNavigation.largestContentfulPaintAllFramesEvt;
123
+ if (!lcpEvent) return;
124
+
125
+ const lcpImagePaintEvent = trace.traceEvents.filter(e => {
126
+ return e.name === 'LargestImagePaint::Candidate' &&
127
+ e.args.frame === lcpEvent.args.frame &&
128
+ e.args.data?.DOMNodeId === lcpEvent.args.data?.nodeId &&
129
+ e.args.data?.size === lcpEvent.args.data?.size;
130
+ // Get last candidate, in case there was more than one.
131
+ }).sort((a, b) => b.ts - a.ts)[0];
132
+
133
+ return lcpImagePaintEvent?.args.data?.imageUrl;
134
+ }
135
+
119
136
  /**
120
137
  * Computes the estimated effect of preloading the LCP image.
121
138
  * @param {LH.Artifacts.TraceElement} lcpElement
@@ -223,15 +240,17 @@ class PreloadLCPImageAudit extends Audit {
223
240
  return {score: null, notApplicable: true};
224
241
  }
225
242
 
226
- const [mainResource, lanternLCP, simulator] = await Promise.all([
243
+ const [processedNavigation, mainResource, lanternLCP, simulator] = await Promise.all([
244
+ ProcessedNavigation.request(trace, context),
227
245
  MainResource.request({devtoolsLog, URL}, context),
228
246
  LanternLargestContentfulPaint.request(metricData, context),
229
247
  LoadSimulator.request({devtoolsLog, settings: context.settings}, context),
230
248
  ]);
231
249
 
250
+ const lcpUrl = PreloadLCPImageAudit.getLcpUrl(trace, processedNavigation);
232
251
  const graph = lanternLCP.pessimisticGraph;
233
252
  // eslint-disable-next-line max-len
234
- const {lcpNodeToPreload, initiatorPath} = PreloadLCPImageAudit.getLCPNodeToPreload(mainResource, graph, lcpElement, artifacts.ImageElements);
253
+ const {lcpNodeToPreload, initiatorPath} = PreloadLCPImageAudit.getLCPNodeToPreload(mainResource, graph, lcpUrl);
235
254
 
236
255
  const {results, wastedMs} =
237
256
  PreloadLCPImageAudit.computeWasteWithGraph(lcpElement, lcpNodeToPreload, graph, simulator);
@@ -80,7 +80,7 @@ declare const MOTOG4_EMULATION_METRICS: Required<LH.SharedFlagsSettings['screenE
80
80
  * @type {Required<LH.SharedFlagsSettings['screenEmulation']>}
81
81
  */
82
82
  declare const DESKTOP_EMULATION_METRICS: Required<LH.SharedFlagsSettings['screenEmulation']>;
83
- declare const MOTOG4_USERAGENT: "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4695.0 Mobile Safari/537.36 Chrome-Lighthouse";
84
- declare const DESKTOP_USERAGENT: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4695.0 Safari/537.36 Chrome-Lighthouse";
83
+ declare const MOTOG4_USERAGENT: "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36";
84
+ declare const DESKTOP_USERAGENT: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36";
85
85
  export {};
86
86
  //# sourceMappingURL=constants.d.ts.map
@@ -81,8 +81,8 @@ const screenEmulationMetrics = {
81
81
  };
82
82
 
83
83
 
84
- const MOTOG4_USERAGENT = 'Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4695.0 Mobile Safari/537.36 Chrome-Lighthouse'; // eslint-disable-line max-len
85
- const DESKTOP_USERAGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4695.0 Safari/537.36 Chrome-Lighthouse'; // eslint-disable-line max-len
84
+ const MOTOG4_USERAGENT = 'Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36'; // eslint-disable-line max-len
85
+ const DESKTOP_USERAGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'; // eslint-disable-line max-len
86
86
 
87
87
  const userAgents = {
88
88
  mobile: MOTOG4_USERAGENT,
@@ -26,6 +26,7 @@ const lcpRelevantAudits = [
26
26
  'unused-javascript',
27
27
  'efficient-animated-content',
28
28
  'total-byte-weight',
29
+ 'lcp-lazy-loaded',
29
30
  ];
30
31
 
31
32
  const tbtRelevantAudits = [
@@ -231,7 +231,7 @@ class TraceElements extends FRGatherer {
231
231
  }
232
232
 
233
233
  // These should exist, but trace types are loose.
234
- const lcpData = processedNavigation.largestContentfulPaintEvt?.args?.data;
234
+ const lcpData = processedNavigation.largestContentfulPaintAllFramesEvt?.args?.data;
235
235
  if (lcpData?.nodeId === undefined || !lcpData.type) return;
236
236
 
237
237
  return {