lighthouse 11.3.0-dev.20231206 → 11.3.0-dev.20231208
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/bf-cache.d.ts +1 -0
- package/core/audits/bf-cache.js +11 -1
- package/core/audits/bootup-time.js +3 -0
- package/core/audits/byte-efficiency/byte-efficiency-audit.js +6 -4
- package/core/audits/byte-efficiency/duplicated-javascript.d.ts +0 -6
- package/core/audits/byte-efficiency/duplicated-javascript.js +9 -37
- package/core/audits/byte-efficiency/legacy-javascript.js +1 -1
- package/core/audits/byte-efficiency/unminified-javascript.js +2 -2
- package/core/audits/byte-efficiency/unused-javascript.js +10 -10
- package/core/audits/layout-shift-elements.js +23 -12
- package/core/audits/metrics/cumulative-layout-shift.js +5 -1
- package/core/audits/resource-summary.d.ts +11 -0
- package/core/audits/resource-summary.js +86 -0
- package/core/audits/third-party-cookies.d.ts +22 -0
- package/core/audits/third-party-cookies.js +112 -0
- package/core/computed/metrics/cumulative-layout-shift.d.ts +13 -1
- package/core/computed/metrics/cumulative-layout-shift.js +47 -1
- package/core/computed/metrics/lantern-first-contentful-paint.d.ts +50 -16
- package/core/computed/metrics/lantern-first-contentful-paint.js +56 -59
- package/core/computed/metrics/lantern-first-meaningful-paint.js +10 -12
- package/core/computed/metrics/lantern-largest-contentful-paint.js +9 -12
- package/core/computed/metrics/lantern-metric.d.ts +2 -2
- package/core/computed/metrics/lantern-metric.js +6 -5
- package/core/config/default-config.js +4 -0
- package/core/config/filters.js +1 -0
- package/core/gather/base-artifacts.js +2 -1
- package/core/gather/gatherers/css-usage.js +5 -0
- package/core/gather/gatherers/trace-elements.d.ts +6 -15
- package/core/gather/gatherers/trace-elements.js +15 -71
- package/core/lib/i18n/i18n.d.ts +2 -2
- package/core/lib/i18n/i18n.js +2 -2
- package/core/lib/network-request.js +4 -1
- package/core/lib/rect-helpers.d.ts +5 -0
- package/core/lib/rect-helpers.js +15 -0
- package/core/lib/script-helpers.d.ts +1 -1
- package/core/lib/script-helpers.js +1 -1
- package/dist/report/bundle.esm.js +3 -3
- package/dist/report/flow.js +5 -5
- package/dist/report/standalone.js +4 -4
- package/package.json +1 -1
- package/report/renderer/performance-category-renderer.js +4 -2
- package/shared/localization/locales/en-US.json +15 -0
- package/shared/localization/locales/en-XL.json +15 -0
- package/tsconfig.json +1 -0
- package/types/artifacts.d.ts +3 -2
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
import BaseGatherer from '../base-gatherer.js';
|
|
16
16
|
import {resolveNodeIdToObjectId} from '../driver/dom.js';
|
|
17
17
|
import {pageFunctions} from '../../lib/page-functions.js';
|
|
18
|
-
import * as RectHelpers from '../../lib/rect-helpers.js';
|
|
19
18
|
import {Sentry} from '../../lib/sentry.js';
|
|
20
19
|
import Trace from './trace.js';
|
|
21
20
|
import {ProcessedTrace} from '../../computed/processed-trace.js';
|
|
@@ -25,7 +24,9 @@ import {Responsiveness} from '../../computed/metrics/responsiveness.js';
|
|
|
25
24
|
import {CumulativeLayoutShift} from '../../computed/metrics/cumulative-layout-shift.js';
|
|
26
25
|
import {ExecutionContext} from '../driver/execution-context.js';
|
|
27
26
|
|
|
28
|
-
/** @typedef {{nodeId: number,
|
|
27
|
+
/** @typedef {{nodeId: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[], type?: string}} TraceElementData */
|
|
28
|
+
|
|
29
|
+
const MAX_LAYOUT_SHIFT_ELEMENTS = 15;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* @this {HTMLElement}
|
|
@@ -63,75 +64,19 @@ class TraceElements extends BaseGatherer {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
x: rect[0],
|
|
72
|
-
y: rect[1],
|
|
73
|
-
width: rect[2],
|
|
74
|
-
height: rect[3],
|
|
75
|
-
};
|
|
76
|
-
return RectHelpers.addRectTopAndBottom(rectArgs);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* This function finds the top (up to 5) elements that contribute to the CLS score of the page.
|
|
81
|
-
* Each layout shift event has a 'score' which is the amount added to the CLS as a result of the given shift(s).
|
|
82
|
-
* We calculate the score per element by taking the 'score' of each layout shift event and
|
|
83
|
-
* distributing it between all the nodes that were shifted, proportianal to the impact region of
|
|
84
|
-
* each shifted element.
|
|
85
|
-
* @param {LH.Artifacts.ProcessedTrace} processedTrace
|
|
86
|
-
* @return {Array<TraceElementData>}
|
|
67
|
+
* This function finds the top (up to 15) elements that contribute to the CLS score of the page.
|
|
68
|
+
*
|
|
69
|
+
* @param {LH.Trace} trace
|
|
70
|
+
* @param {LH.Gatherer.Context} context
|
|
71
|
+
* @return {Promise<Array<TraceElementData>>}
|
|
87
72
|
*/
|
|
88
|
-
static getTopLayoutShiftElements(
|
|
89
|
-
|
|
90
|
-
const clsPerNode = new Map();
|
|
91
|
-
const shiftEvents = CumulativeLayoutShift.getLayoutShiftEvents(processedTrace);
|
|
73
|
+
static async getTopLayoutShiftElements(trace, context) {
|
|
74
|
+
const {impactByNodeId} = await CumulativeLayoutShift.request(trace, context);
|
|
92
75
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
let totalAreaOfImpact = 0;
|
|
99
|
-
/** @type {Map<number, number>} */
|
|
100
|
-
const pixelsMovedPerNode = new Map();
|
|
101
|
-
|
|
102
|
-
event.impactedNodes.forEach(node => {
|
|
103
|
-
if (!node.node_id || !node.old_rect || !node.new_rect) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const oldRect = TraceElements.traceRectToLHRect(node.old_rect);
|
|
108
|
-
const newRect = TraceElements.traceRectToLHRect(node.new_rect);
|
|
109
|
-
const areaOfImpact = RectHelpers.getRectArea(oldRect) +
|
|
110
|
-
RectHelpers.getRectArea(newRect) -
|
|
111
|
-
RectHelpers.getRectOverlapArea(oldRect, newRect);
|
|
112
|
-
|
|
113
|
-
pixelsMovedPerNode.set(node.node_id, areaOfImpact);
|
|
114
|
-
totalAreaOfImpact += areaOfImpact;
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
for (const [nodeId, pixelsMoved] of pixelsMovedPerNode.entries()) {
|
|
118
|
-
let clsContribution = clsPerNode.get(nodeId) || 0;
|
|
119
|
-
clsContribution += (pixelsMoved / totalAreaOfImpact) * event.weightedScore;
|
|
120
|
-
clsPerNode.set(nodeId, clsContribution);
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const topFive = [...clsPerNode.entries()]
|
|
125
|
-
.sort((a, b) => b[1] - a[1])
|
|
126
|
-
.slice(0, 5)
|
|
127
|
-
.map(([nodeId, clsContribution]) => {
|
|
128
|
-
return {
|
|
129
|
-
nodeId: nodeId,
|
|
130
|
-
score: clsContribution,
|
|
131
|
-
};
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
return topFive;
|
|
76
|
+
return [...impactByNodeId.entries()]
|
|
77
|
+
.sort((a, b) => b[1] - a[1])
|
|
78
|
+
.slice(0, MAX_LAYOUT_SHIFT_ELEMENTS)
|
|
79
|
+
.map(([nodeId]) => ({nodeId}));
|
|
135
80
|
}
|
|
136
81
|
|
|
137
82
|
/**
|
|
@@ -265,7 +210,7 @@ class TraceElements extends BaseGatherer {
|
|
|
265
210
|
const {mainThreadEvents} = processedTrace;
|
|
266
211
|
|
|
267
212
|
const lcpNodeData = await TraceElements.getLcpElement(trace, context);
|
|
268
|
-
const clsNodeData = TraceElements.getTopLayoutShiftElements(
|
|
213
|
+
const clsNodeData = await TraceElements.getTopLayoutShiftElements(trace, context);
|
|
269
214
|
const animatedElementData = await this.getAnimatedElements(mainThreadEvents);
|
|
270
215
|
const responsivenessElementData = await TraceElements.getResponsivenessElement(trace, context);
|
|
271
216
|
|
|
@@ -311,7 +256,6 @@ class TraceElements extends BaseGatherer {
|
|
|
311
256
|
traceElements.push({
|
|
312
257
|
traceEventType,
|
|
313
258
|
...response.result.value,
|
|
314
|
-
score: backendNodeData[i].score,
|
|
315
259
|
animations: backendNodeData[i].animations,
|
|
316
260
|
nodeId: backendNodeId,
|
|
317
261
|
type: backendNodeData[i].type,
|
package/core/lib/i18n/i18n.d.ts
CHANGED
|
@@ -69,9 +69,9 @@ export function lookupLocale(locales?: (string | string[]) | undefined, possible
|
|
|
69
69
|
* Returns a function that generates `LH.IcuMessage` objects to localize the
|
|
70
70
|
* messages in `fileStrings` and the shared `i18n.UIStrings`.
|
|
71
71
|
* @param {string} filename
|
|
72
|
-
* @param {Record<string, string
|
|
72
|
+
* @param {Record<string, string>=} fileStrings
|
|
73
73
|
*/
|
|
74
|
-
export function createIcuMessageFn(filename: string, fileStrings
|
|
74
|
+
export function createIcuMessageFn(filename: string, fileStrings?: Record<string, string> | undefined): (message: string, values?: Record<string, string | number> | undefined) => LH.IcuMessage;
|
|
75
75
|
/**
|
|
76
76
|
* Returns true if the given value is a string or an LH.IcuMessage.
|
|
77
77
|
* @param {unknown} value
|
package/core/lib/i18n/i18n.js
CHANGED
|
@@ -168,9 +168,9 @@ function lookupLocale(locales, possibleLocales) {
|
|
|
168
168
|
* Returns a function that generates `LH.IcuMessage` objects to localize the
|
|
169
169
|
* messages in `fileStrings` and the shared `i18n.UIStrings`.
|
|
170
170
|
* @param {string} filename
|
|
171
|
-
* @param {Record<string, string
|
|
171
|
+
* @param {Record<string, string>=} fileStrings
|
|
172
172
|
*/
|
|
173
|
-
function createIcuMessageFn(filename, fileStrings) {
|
|
173
|
+
function createIcuMessageFn(filename, fileStrings = {}) {
|
|
174
174
|
if (filename.startsWith('file://')) filename = url.fileURLToPath(filename);
|
|
175
175
|
|
|
176
176
|
// In the common case, `filename` is an absolute path that needs to be transformed
|
|
@@ -614,7 +614,10 @@ class NetworkRequest {
|
|
|
614
614
|
* @return {boolean}
|
|
615
615
|
*/
|
|
616
616
|
static isContentEncoded(record) {
|
|
617
|
-
|
|
617
|
+
// FYI: older devtools logs (like our test fixtures) seems to be lower case, while modern logs
|
|
618
|
+
// are Cased-Like-This.
|
|
619
|
+
const pattern = /^content-encoding$/i;
|
|
620
|
+
return record.responseHeaders.some(item => item.name.match(pattern));
|
|
618
621
|
}
|
|
619
622
|
|
|
620
623
|
/**
|
|
@@ -97,4 +97,9 @@ export function filterOutRectsContainedByOthers(rects: LH.Artifacts.Rect[]): LH.
|
|
|
97
97
|
* @return {LH.Artifacts.Rect[]}
|
|
98
98
|
*/
|
|
99
99
|
export function filterOutTinyRects(rects: LH.Artifacts.Rect[]): LH.Artifacts.Rect[];
|
|
100
|
+
/**
|
|
101
|
+
* @param {Array<number>} rect
|
|
102
|
+
* @return {LH.Artifacts.Rect}
|
|
103
|
+
*/
|
|
104
|
+
export function traceRectToLHRect(rect: Array<number>): LH.Artifacts.Rect;
|
|
100
105
|
//# sourceMappingURL=rect-helpers.d.ts.map
|
package/core/lib/rect-helpers.js
CHANGED
|
@@ -232,6 +232,20 @@ function allRectsContainedWithinEachOther(rectListA, rectListB) {
|
|
|
232
232
|
return true;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
+
/**
|
|
236
|
+
* @param {Array<number>} rect
|
|
237
|
+
* @return {LH.Artifacts.Rect}
|
|
238
|
+
*/
|
|
239
|
+
function traceRectToLHRect(rect) {
|
|
240
|
+
const rectArgs = {
|
|
241
|
+
x: rect[0],
|
|
242
|
+
y: rect[1],
|
|
243
|
+
width: rect[2],
|
|
244
|
+
height: rect[3],
|
|
245
|
+
};
|
|
246
|
+
return addRectTopAndBottom(rectArgs);
|
|
247
|
+
}
|
|
248
|
+
|
|
235
249
|
export {
|
|
236
250
|
rectContainsPoint,
|
|
237
251
|
rectContains,
|
|
@@ -248,4 +262,5 @@ export {
|
|
|
248
262
|
allRectsContainedWithinEachOther,
|
|
249
263
|
filterOutRectsContainedByOthers,
|
|
250
264
|
filterOutTinyRects,
|
|
265
|
+
traceRectToLHRect,
|
|
251
266
|
};
|
|
@@ -41,6 +41,6 @@ export function estimateTransferSize(networkRecord: LH.Artifacts.NetworkRequest
|
|
|
41
41
|
* @param {LH.Artifacts} artifacts
|
|
42
42
|
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
43
43
|
*/
|
|
44
|
-
export function estimateCompressionRatioForContent(compressionRatioByUrl: Map<string, number>, url: string, artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>):
|
|
44
|
+
export function estimateCompressionRatioForContent(compressionRatioByUrl: Map<string, number>, url: string, artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>): number;
|
|
45
45
|
import { NetworkRequest } from './network-request.js';
|
|
46
46
|
//# sourceMappingURL=script-helpers.d.ts.map
|
|
@@ -137,7 +137,7 @@ function estimateCompressedContentSize(networkRecord, totalBytes, resourceType)
|
|
|
137
137
|
* @param {LH.Artifacts} artifacts
|
|
138
138
|
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
139
139
|
*/
|
|
140
|
-
|
|
140
|
+
function estimateCompressionRatioForContent(compressionRatioByUrl, url,
|
|
141
141
|
artifacts, networkRecords) {
|
|
142
142
|
let compressionRatio = compressionRatioByUrl.get(url);
|
|
143
143
|
if (compressionRatio !== undefined) return compressionRatio;
|