lighthouse 9.6.6 → 9.6.7
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/lighthouse-core/audits/lcp-lazy-loaded.js +4 -3
- package/lighthouse-core/audits/network-requests.js +1 -0
- package/lighthouse-core/audits/preload-lcp-image.js +7 -3
- package/lighthouse-core/gather/gatherers/trace-elements.js +32 -13
- package/package.json +1 -1
- package/types/artifacts.d.ts +1 -0
- package/changelog.md +0 -6059
|
@@ -50,8 +50,9 @@ class LargestContentfulPaintLazyLoaded extends Audit {
|
|
|
50
50
|
* @return {LH.Audit.Product}
|
|
51
51
|
*/
|
|
52
52
|
static audit(artifacts) {
|
|
53
|
-
const lcpElement = artifacts.TraceElements
|
|
54
|
-
|
|
53
|
+
const lcpElement = artifacts.TraceElements.find(element => {
|
|
54
|
+
return element.traceEventType === 'largest-contentful-paint' && element.type === 'image';
|
|
55
|
+
});
|
|
55
56
|
const lcpElementImage = lcpElement ? artifacts.ImageElements.find(elem => {
|
|
56
57
|
return elem.node.devtoolsNodePath === lcpElement.node.devtoolsNodePath;
|
|
57
58
|
}) : undefined;
|
|
@@ -59,7 +60,7 @@ class LargestContentfulPaintLazyLoaded extends Audit {
|
|
|
59
60
|
|
|
60
61
|
if (!lcpElementImage ||
|
|
61
62
|
!this.isImageInViewport(lcpElementImage, artifacts.ViewportDimensions)) {
|
|
62
|
-
return {score:
|
|
63
|
+
return {score: null, notApplicable: true};
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
@@ -73,6 +73,7 @@ class NetworkRequests extends Audit {
|
|
|
73
73
|
statusCode: record.statusCode,
|
|
74
74
|
mimeType: record.mimeType,
|
|
75
75
|
resourceType: record.resourceType,
|
|
76
|
+
priority: record.priority,
|
|
76
77
|
isLinkPreload,
|
|
77
78
|
experimentalFromMainFrame,
|
|
78
79
|
lrEndTimeDeltaMs: endTimeDeltaMs, // Only exists on Lightrider runs
|
|
@@ -88,7 +88,7 @@ class PreloadLCPImageAudit extends Audit {
|
|
|
88
88
|
/**
|
|
89
89
|
* @param {LH.Artifacts.NetworkRequest} mainResource
|
|
90
90
|
* @param {LH.Gatherer.Simulation.GraphNode} graph
|
|
91
|
-
* @param {LH.Artifacts.TraceElement
|
|
91
|
+
* @param {LH.Artifacts.TraceElement} lcpElement
|
|
92
92
|
* @param {Array<LH.Artifacts.ImageElement>} imageElements
|
|
93
93
|
* @return {{lcpNodeToPreload?: LH.Gatherer.Simulation.GraphNetworkNode, initiatorPath?: InitiatorPath}}
|
|
94
94
|
*/
|
|
@@ -121,14 +121,14 @@ class PreloadLCPImageAudit extends Audit {
|
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* Computes the estimated effect of preloading the LCP image.
|
|
124
|
-
* @param {LH.Artifacts.TraceElement
|
|
124
|
+
* @param {LH.Artifacts.TraceElement} lcpElement
|
|
125
125
|
* @param {LH.Gatherer.Simulation.GraphNetworkNode|undefined} lcpNode
|
|
126
126
|
* @param {LH.Gatherer.Simulation.GraphNode} graph
|
|
127
127
|
* @param {LH.Gatherer.Simulation.Simulator} simulator
|
|
128
128
|
* @return {{wastedMs: number, results: Array<{node: LH.Audit.Details.NodeValue, url: string, wastedMs: number}>}}
|
|
129
129
|
*/
|
|
130
130
|
static computeWasteWithGraph(lcpElement, lcpNode, graph, simulator) {
|
|
131
|
-
if (!
|
|
131
|
+
if (!lcpNode) {
|
|
132
132
|
return {
|
|
133
133
|
wastedMs: 0,
|
|
134
134
|
results: [],
|
|
@@ -222,6 +222,10 @@ class PreloadLCPImageAudit extends Audit {
|
|
|
222
222
|
const lcpElement = artifacts.TraceElements
|
|
223
223
|
.find(element => element.traceEventType === 'largest-contentful-paint');
|
|
224
224
|
|
|
225
|
+
if (!lcpElement || lcpElement.type !== 'image') {
|
|
226
|
+
return {score: null, notApplicable: true};
|
|
227
|
+
}
|
|
228
|
+
|
|
225
229
|
const [mainResource, lanternLCP, simulator] = await Promise.all([
|
|
226
230
|
MainResource.request({devtoolsLog, URL}, context),
|
|
227
231
|
LanternLCP.request(metricData, context),
|
|
@@ -24,7 +24,7 @@ const ProcessedNavigation = require('../../computed/processed-navigation.js');
|
|
|
24
24
|
const LighthouseError = require('../../lib/lh-error.js');
|
|
25
25
|
const ComputedResponsivenes = require('../../computed/metrics/responsiveness.js');
|
|
26
26
|
|
|
27
|
-
/** @typedef {{nodeId: number, score?: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[]}} TraceElementData */
|
|
27
|
+
/** @typedef {{nodeId: number, score?: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[], type?: string}} TraceElementData */
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* @this {HTMLElement}
|
|
@@ -213,6 +213,34 @@ class TraceElements extends FRGatherer {
|
|
|
213
213
|
return animatedElementData;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* @param {LH.Artifacts.ProcessedTrace} processedTrace
|
|
218
|
+
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
219
|
+
* @return {Promise<{nodeId: number, type: string} | undefined>}
|
|
220
|
+
*/
|
|
221
|
+
static async getLcpElement(processedTrace, context) {
|
|
222
|
+
let processedNavigation;
|
|
223
|
+
try {
|
|
224
|
+
processedNavigation = await ProcessedNavigation.request(processedTrace, context);
|
|
225
|
+
} catch (err) {
|
|
226
|
+
// If we were running in timespan mode and there was no paint, treat LCP as missing.
|
|
227
|
+
if (context.gatherMode === 'timespan' && err.code === LighthouseError.errors.NO_FCP.code) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
throw err;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// These should exist, but trace types are loose.
|
|
235
|
+
const lcpData = processedNavigation.largestContentfulPaintEvt?.args?.data;
|
|
236
|
+
if (lcpData?.nodeId === undefined || !lcpData.type) return;
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
nodeId: lcpData.nodeId,
|
|
240
|
+
type: lcpData.type,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
216
244
|
/**
|
|
217
245
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
218
246
|
*/
|
|
@@ -241,26 +269,16 @@ class TraceElements extends FRGatherer {
|
|
|
241
269
|
}
|
|
242
270
|
|
|
243
271
|
const processedTrace = await ProcessedTrace.request(trace, context);
|
|
244
|
-
const {largestContentfulPaintEvt} = await ProcessedNavigation
|
|
245
|
-
.request(processedTrace, context)
|
|
246
|
-
.catch(err => {
|
|
247
|
-
// If we were running in timespan mode and there was no paint, treat LCP as missing.
|
|
248
|
-
if (context.gatherMode === 'timespan' && err.code === LighthouseError.errors.NO_FCP.code) {
|
|
249
|
-
return {largestContentfulPaintEvt: undefined};
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
throw err;
|
|
253
|
-
});
|
|
254
272
|
const {mainThreadEvents} = processedTrace;
|
|
255
273
|
|
|
256
|
-
const
|
|
274
|
+
const lcpNodeData = await TraceElements.getLcpElement(processedTrace, context);
|
|
257
275
|
const clsNodeData = TraceElements.getTopLayoutShiftElements(mainThreadEvents);
|
|
258
276
|
const animatedElementData = await this.getAnimatedElements(mainThreadEvents);
|
|
259
277
|
const responsivenessElementData = await TraceElements.getResponsivenessElement(trace, context);
|
|
260
278
|
|
|
261
279
|
/** @type {Map<string, TraceElementData[]>} */
|
|
262
280
|
const backendNodeDataMap = new Map([
|
|
263
|
-
['largest-contentful-paint',
|
|
281
|
+
['largest-contentful-paint', lcpNodeData ? [lcpNodeData] : []],
|
|
264
282
|
['layout-shift', clsNodeData],
|
|
265
283
|
['animation', animatedElementData],
|
|
266
284
|
['responsiveness', responsivenessElementData ? [responsivenessElementData] : []],
|
|
@@ -299,6 +317,7 @@ class TraceElements extends FRGatherer {
|
|
|
299
317
|
score: backendNodeData[i].score,
|
|
300
318
|
animations: backendNodeData[i].animations,
|
|
301
319
|
nodeId: backendNodeId,
|
|
320
|
+
type: backendNodeData[i].type,
|
|
302
321
|
});
|
|
303
322
|
}
|
|
304
323
|
}
|
package/package.json
CHANGED
package/types/artifacts.d.ts
CHANGED