lighthouse 11.7.0-dev.20240410 → 11.7.0-dev.20240411
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/byte-efficiency/render-blocking-resources.js +25 -26
- package/core/audits/layout-shifts.js +1 -1
- package/core/computed/metrics/lantern-first-contentful-paint.js +3 -2
- package/core/computed/metrics/lantern-first-meaningful-paint.js +3 -2
- package/core/computed/metrics/lantern-interactive.js +3 -2
- package/core/computed/metrics/lantern-largest-contentful-paint.js +3 -2
- package/core/computed/metrics/lantern-max-potential-fid.js +3 -2
- package/core/computed/metrics/lantern-metric.d.ts +5 -0
- package/core/computed/metrics/lantern-metric.js +23 -1
- package/core/computed/metrics/lantern-speed-index.js +3 -2
- package/core/computed/navigation-insights.d.ts +36 -0
- package/core/computed/navigation-insights.js +35 -0
- package/core/computed/trace-engine-result.d.ts +16 -3
- package/core/computed/trace-engine-result.js +19 -14
- package/core/config/default-config.js +0 -1
- package/core/config/filters.js +0 -1
- package/core/gather/gatherers/root-causes.d.ts +2 -2
- package/core/gather/gatherers/root-causes.js +6 -5
- package/core/gather/gatherers/trace-elements.d.ts +2 -2
- package/core/gather/gatherers/trace-elements.js +2 -2
- package/core/lib/lantern/cpu-node.d.ts +7 -1
- package/core/lib/lantern/cpu-node.js +12 -2
- package/core/lib/lantern/lantern-error.d.ts +8 -0
- package/core/lib/lantern/lantern-error.js +9 -0
- package/core/lib/lantern/metrics/first-meaningful-paint.js +2 -4
- package/core/lib/lantern/metrics/interactive.js +1 -1
- package/core/lib/lantern/metrics/largest-contentful-paint.js +3 -3
- package/core/lib/lantern/page-dependency-graph.js +14 -2
- package/core/lib/lantern/simulator/simulator.js +1 -1
- package/core/lib/lh-error.js +3 -3
- package/core/runner.js +0 -1
- package/package.json +1 -1
- package/tsconfig.json +0 -1
- package/types/artifacts.d.ts +15 -63
- package/types/lhr/lhr.d.ts +0 -2
- package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +0 -47
- package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +0 -233
|
@@ -14,10 +14,10 @@ import * as i18n from '../../lib/i18n/i18n.js';
|
|
|
14
14
|
import {BaseNode} from '../../lib/lantern/base-node.js';
|
|
15
15
|
import {UnusedCSS} from '../../computed/unused-css.js';
|
|
16
16
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
17
|
-
import {ProcessedNavigation} from '../../computed/processed-navigation.js';
|
|
18
17
|
import {LoadSimulator} from '../../computed/load-simulator.js';
|
|
19
18
|
import {FirstContentfulPaint} from '../../computed/metrics/first-contentful-paint.js';
|
|
20
19
|
import {LCPImageRecord} from '../../computed/lcp-image-record.js';
|
|
20
|
+
import {NavigationInsights} from '../../computed/navigation-insights.js';
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
/** @typedef {import('../../lib/lantern/simulator/simulator.js').Simulator} Simulator */
|
|
@@ -44,21 +44,19 @@ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
|
44
44
|
/**
|
|
45
45
|
* Given a simulation's nodeTimings, return an object with the nodes/timing keyed by network URL
|
|
46
46
|
* @param {LH.Gatherer.Simulation.Result['nodeTimings']} nodeTimings
|
|
47
|
-
* @return {
|
|
47
|
+
* @return {Map<string, {node: Node, nodeTiming: LH.Gatherer.Simulation.NodeTiming}>}
|
|
48
48
|
*/
|
|
49
|
-
function
|
|
50
|
-
/** @type {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (node.type !== 'network')
|
|
55
|
-
const nodeTiming = nodeTimings.get(node);
|
|
56
|
-
if (!nodeTiming) return;
|
|
57
|
-
|
|
58
|
-
urlMap[node.record.url] = {node, nodeTiming};
|
|
59
|
-
});
|
|
49
|
+
function getNodesAndTimingByRequestId(nodeTimings) {
|
|
50
|
+
/** @type {Map<string, {node: Node, nodeTiming: LH.Gatherer.Simulation.NodeTiming}>} */
|
|
51
|
+
const requestIdToNode = new Map();
|
|
52
|
+
|
|
53
|
+
for (const [node, nodeTiming] of nodeTimings) {
|
|
54
|
+
if (node.type !== 'network') continue;
|
|
60
55
|
|
|
61
|
-
|
|
56
|
+
requestIdToNode.set(node.record.requestId, {node, nodeTiming});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return requestIdToNode;
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
/**
|
|
@@ -119,8 +117,7 @@ class RenderBlockingResources extends Audit {
|
|
|
119
117
|
guidanceLevel: 2,
|
|
120
118
|
// TODO: look into adding an `optionalArtifacts` property that captures the non-required nature
|
|
121
119
|
// of CSSUsage
|
|
122
|
-
requiredArtifacts: ['URL', '
|
|
123
|
-
'GatherContext', 'Stacks'],
|
|
120
|
+
requiredArtifacts: ['URL', 'traces', 'devtoolsLogs', 'CSSUsage', 'GatherContext', 'Stacks'],
|
|
124
121
|
};
|
|
125
122
|
}
|
|
126
123
|
|
|
@@ -134,9 +131,12 @@ class RenderBlockingResources extends Audit {
|
|
|
134
131
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
135
132
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
136
133
|
const simulatorData = {devtoolsLog, settings: context.settings};
|
|
137
|
-
const processedNavigation = await ProcessedNavigation.request(trace, context);
|
|
138
134
|
const simulator = await LoadSimulator.request(simulatorData, context);
|
|
139
135
|
const wastedCssBytes = await RenderBlockingResources.computeWastedCSSBytes(artifacts, context);
|
|
136
|
+
const navInsights = await NavigationInsights.request(trace, context);
|
|
137
|
+
|
|
138
|
+
const renderBlocking = navInsights.RenderBlocking;
|
|
139
|
+
if (renderBlocking instanceof Error) throw renderBlocking;
|
|
140
140
|
|
|
141
141
|
/** @type {LH.Audit.Context['settings']} */
|
|
142
142
|
const metricSettings = {
|
|
@@ -150,19 +150,18 @@ class RenderBlockingResources extends Audit {
|
|
|
150
150
|
// Cast to just `LanternMetric` since we explicitly set `throttlingMethod: 'simulate'`.
|
|
151
151
|
const fcpSimulation = /** @type {LH.Artifacts.LanternMetric} */
|
|
152
152
|
(await FirstContentfulPaint.request(metricComputationData, context));
|
|
153
|
-
const fcpTsInMs = processedNavigation.timestamps.firstContentfulPaint / 1000;
|
|
154
153
|
|
|
155
|
-
const
|
|
154
|
+
const nodesAndTimingsByRequestId =
|
|
155
|
+
getNodesAndTimingByRequestId(fcpSimulation.optimisticEstimate.nodeTimings);
|
|
156
156
|
|
|
157
157
|
const results = [];
|
|
158
158
|
const deferredNodeIds = new Set();
|
|
159
|
-
for (const resource of
|
|
160
|
-
|
|
161
|
-
if (resource.endTime > fcpTsInMs) continue;
|
|
159
|
+
for (const resource of renderBlocking.renderBlockingRequests) {
|
|
160
|
+
const nodeAndTiming = nodesAndTimingsByRequestId.get(resource.args.data.requestId);
|
|
162
161
|
// TODO: beacon to Sentry, https://github.com/GoogleChrome/lighthouse/issues/7041
|
|
163
|
-
if (!
|
|
162
|
+
if (!nodeAndTiming) continue;
|
|
164
163
|
|
|
165
|
-
const {node, nodeTiming} =
|
|
164
|
+
const {node, nodeTiming} = nodeAndTiming;
|
|
166
165
|
|
|
167
166
|
const stackSpecificTiming = computeStackSpecificTiming(node, nodeTiming, artifacts.Stacks);
|
|
168
167
|
|
|
@@ -174,8 +173,8 @@ class RenderBlockingResources extends Audit {
|
|
|
174
173
|
if (wastedMs < MINIMUM_WASTED_MS) continue;
|
|
175
174
|
|
|
176
175
|
results.push({
|
|
177
|
-
url: resource.
|
|
178
|
-
totalBytes: resource.
|
|
176
|
+
url: resource.args.data.url,
|
|
177
|
+
totalBytes: resource.args.data.encodedDataLength,
|
|
179
178
|
wastedMs,
|
|
180
179
|
});
|
|
181
180
|
}
|
|
@@ -61,7 +61,7 @@ class LayoutShifts extends Audit {
|
|
|
61
61
|
static async audit(artifacts, context) {
|
|
62
62
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
63
63
|
const traceEngineResult = await TraceEngineResult.request({trace}, context);
|
|
64
|
-
const clusters = traceEngineResult.LayoutShifts.clusters ?? [];
|
|
64
|
+
const clusters = traceEngineResult.data.LayoutShifts.clusters ?? [];
|
|
65
65
|
const {cumulativeLayoutShift: clsSavings, impactByNodeId} =
|
|
66
66
|
await CumulativeLayoutShiftComputed.request(trace, context);
|
|
67
67
|
const traceElements = artifacts.TraceElements
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
|
-
import {getComputationDataParams} from './lantern-metric.js';
|
|
8
|
+
import {getComputationDataParams, lanternErrorAdapter} from './lantern-metric.js';
|
|
9
9
|
import {FirstContentfulPaint} from '../../lib/lantern/metrics/first-contentful-paint.js';
|
|
10
10
|
|
|
11
11
|
/** @typedef {import('../../lib/lantern/metric.js').Extras} Extras */
|
|
@@ -18,7 +18,8 @@ class LanternFirstContentfulPaint extends FirstContentfulPaint {
|
|
|
18
18
|
* @return {Promise<LH.Artifacts.LanternMetric>}
|
|
19
19
|
*/
|
|
20
20
|
static async computeMetricWithGraphs(data, context, extras) {
|
|
21
|
-
return this.compute(await getComputationDataParams(data, context), extras)
|
|
21
|
+
return this.compute(await getComputationDataParams(data, context), extras)
|
|
22
|
+
.catch(lanternErrorAdapter);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
|
-
import {getComputationDataParams} from './lantern-metric.js';
|
|
8
|
+
import {getComputationDataParams, lanternErrorAdapter} from './lantern-metric.js';
|
|
9
9
|
import {FirstMeaningfulPaint} from '../../lib/lantern/metrics/first-meaningful-paint.js';
|
|
10
10
|
import {LanternFirstContentfulPaint} from './lantern-first-contentful-paint.js';
|
|
11
11
|
|
|
@@ -19,7 +19,8 @@ class LanternFirstMeaningfulPaint extends FirstMeaningfulPaint {
|
|
|
19
19
|
* @return {Promise<LH.Artifacts.LanternMetric>}
|
|
20
20
|
*/
|
|
21
21
|
static async computeMetricWithGraphs(data, context, extras) {
|
|
22
|
-
return this.compute(await getComputationDataParams(data, context), extras)
|
|
22
|
+
return this.compute(await getComputationDataParams(data, context), extras)
|
|
23
|
+
.catch(lanternErrorAdapter);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
8
|
import {LanternFirstMeaningfulPaint} from './lantern-first-meaningful-paint.js';
|
|
9
9
|
import {Interactive} from '../../lib/lantern/metrics/interactive.js';
|
|
10
|
-
import {getComputationDataParams} from './lantern-metric.js';
|
|
10
|
+
import {getComputationDataParams, lanternErrorAdapter} from './lantern-metric.js';
|
|
11
11
|
|
|
12
12
|
/** @typedef {import('../../lib/lantern/metric.js').Extras} Extras */
|
|
13
13
|
|
|
@@ -19,7 +19,8 @@ class LanternInteractive extends Interactive {
|
|
|
19
19
|
* @return {Promise<LH.Artifacts.LanternMetric>}
|
|
20
20
|
*/
|
|
21
21
|
static async computeMetricWithGraphs(data, context, extras) {
|
|
22
|
-
return this.compute(await getComputationDataParams(data, context), extras)
|
|
22
|
+
return this.compute(await getComputationDataParams(data, context), extras)
|
|
23
|
+
.catch(lanternErrorAdapter);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
8
|
import {LargestContentfulPaint} from '../../lib/lantern/metrics/largest-contentful-paint.js';
|
|
9
|
-
import {getComputationDataParams} from './lantern-metric.js';
|
|
9
|
+
import {getComputationDataParams, lanternErrorAdapter} from './lantern-metric.js';
|
|
10
10
|
import {LanternFirstContentfulPaint} from './lantern-first-contentful-paint.js';
|
|
11
11
|
|
|
12
12
|
/** @typedef {import('../../lib/lantern/metric.js').Extras} Extras */
|
|
@@ -19,7 +19,8 @@ class LanternLargestContentfulPaint extends LargestContentfulPaint {
|
|
|
19
19
|
* @return {Promise<LH.Artifacts.LanternMetric>}
|
|
20
20
|
*/
|
|
21
21
|
static async computeMetricWithGraphs(data, context, extras) {
|
|
22
|
-
return this.compute(await getComputationDataParams(data, context), extras)
|
|
22
|
+
return this.compute(await getComputationDataParams(data, context), extras)
|
|
23
|
+
.catch(lanternErrorAdapter);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
8
|
import {MaxPotentialFID} from '../../lib/lantern/metrics/max-potential-fid.js';
|
|
9
|
-
import {getComputationDataParams} from './lantern-metric.js';
|
|
9
|
+
import {getComputationDataParams, lanternErrorAdapter} from './lantern-metric.js';
|
|
10
10
|
import {LanternFirstContentfulPaint} from './lantern-first-contentful-paint.js';
|
|
11
11
|
|
|
12
12
|
/** @typedef {import('../../lib/lantern/metric.js').Extras} Extras */
|
|
@@ -19,7 +19,8 @@ class LanternMaxPotentialFID extends MaxPotentialFID {
|
|
|
19
19
|
* @return {Promise<LH.Artifacts.LanternMetric>}
|
|
20
20
|
*/
|
|
21
21
|
static async computeMetricWithGraphs(data, context, extras) {
|
|
22
|
-
return this.compute(await getComputationDataParams(data, context), extras)
|
|
22
|
+
return this.compute(await getComputationDataParams(data, context), extras)
|
|
23
|
+
.catch(lanternErrorAdapter);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -7,4 +7,9 @@ export function getComputationDataParams(data: LH.Artifacts.MetricComputationDat
|
|
|
7
7
|
graph: import("../page-dependency-graph.js").Node;
|
|
8
8
|
processedNavigation: import("../../index.js").Artifacts.ProcessedNavigation;
|
|
9
9
|
}>;
|
|
10
|
+
/**
|
|
11
|
+
* @param {unknown} err
|
|
12
|
+
* @return {never}
|
|
13
|
+
*/
|
|
14
|
+
export function lanternErrorAdapter(err: unknown): never;
|
|
10
15
|
//# sourceMappingURL=lantern-metric.d.ts.map
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import {LanternError} from '../../lib/lantern/lantern-error.js';
|
|
8
|
+
import {LighthouseError} from '../../lib/lh-error.js';
|
|
7
9
|
import {LoadSimulator} from '../load-simulator.js';
|
|
8
10
|
import {PageDependencyGraph} from '../page-dependency-graph.js';
|
|
9
11
|
import {ProcessedNavigation} from '../processed-navigation.js';
|
|
@@ -24,4 +26,24 @@ async function getComputationDataParams(data, context) {
|
|
|
24
26
|
return {simulator, graph, processedNavigation};
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
/**
|
|
30
|
+
* @param {unknown} err
|
|
31
|
+
* @return {never}
|
|
32
|
+
*/
|
|
33
|
+
function lanternErrorAdapter(err) {
|
|
34
|
+
if (!(err instanceof LanternError)) {
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const code = /** @type {keyof LighthouseError.errors} */ (err.message);
|
|
39
|
+
if (LighthouseError.errors[code]) {
|
|
40
|
+
throw new LighthouseError(LighthouseError.errors[code]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
getComputationDataParams,
|
|
48
|
+
lanternErrorAdapter,
|
|
49
|
+
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
|
-
import {getComputationDataParams} from './lantern-metric.js';
|
|
8
|
+
import {getComputationDataParams, lanternErrorAdapter} from './lantern-metric.js';
|
|
9
9
|
import {Speedline} from '../speedline.js';
|
|
10
10
|
import {LanternFirstContentfulPaint} from './lantern-first-contentful-paint.js';
|
|
11
11
|
import {SpeedIndex} from '../../lib/lantern/metrics/speed-index.js';
|
|
@@ -20,7 +20,8 @@ class LanternSpeedIndex extends SpeedIndex {
|
|
|
20
20
|
* @return {Promise<LH.Artifacts.LanternMetric>}
|
|
21
21
|
*/
|
|
22
22
|
static async computeMetricWithGraphs(data, context, extras) {
|
|
23
|
-
return this.compute(await getComputationDataParams(data, context), extras)
|
|
23
|
+
return this.compute(await getComputationDataParams(data, context), extras)
|
|
24
|
+
.catch(lanternErrorAdapter);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export { NavigationInsightsComputed as NavigationInsights };
|
|
2
|
+
declare const NavigationInsightsComputed: typeof NavigationInsights & {
|
|
3
|
+
request: (dependencies: import("../index.js").Trace, context: import("../../types/utility-types.js").default.ImmutableObject<{
|
|
4
|
+
computedCache: Map<string, import("../lib/arbitrary-equality-map.js").ArbitraryEqualityMap>;
|
|
5
|
+
}>) => Promise<import("@paulirish/trace_engine/models/trace/insights/types.js").NavigationInsightData<{
|
|
6
|
+
AuctionWorklets: typeof import("@paulirish/trace_engine/models/trace/handlers/AuctionWorkletsHandler.js");
|
|
7
|
+
Initiators: typeof import("@paulirish/trace_engine/models/trace/handlers/InitiatorsHandler.js");
|
|
8
|
+
LayoutShifts: typeof import("@paulirish/trace_engine/models/trace/handlers/LayoutShiftsHandler.js");
|
|
9
|
+
NetworkRequests: typeof import("@paulirish/trace_engine/models/trace/handlers/NetworkRequestsHandler.js");
|
|
10
|
+
Renderer: typeof import("@paulirish/trace_engine/models/trace/handlers/RendererHandler.js");
|
|
11
|
+
Samples: typeof import("@paulirish/trace_engine/models/trace/handlers/SamplesHandler.js");
|
|
12
|
+
Screenshots: typeof import("@paulirish/trace_engine/models/trace/handlers/ScreenshotsHandler.js");
|
|
13
|
+
PageLoadMetrics: typeof import("@paulirish/trace_engine/models/trace/handlers/PageLoadMetricsHandler.js");
|
|
14
|
+
}>>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @fileoverview Gets insights from the shared trace engine for the navigation audited by Lighthouse.
|
|
18
|
+
* Only usable in navigation mode.
|
|
19
|
+
*/
|
|
20
|
+
declare class NavigationInsights {
|
|
21
|
+
/**
|
|
22
|
+
* @param {LH.Trace} trace
|
|
23
|
+
* @param {LH.Artifacts.ComputedContext} context
|
|
24
|
+
*/
|
|
25
|
+
static compute_(trace: LH.Trace, context: LH.Artifacts.ComputedContext): Promise<import("@paulirish/trace_engine/models/trace/insights/types.js").NavigationInsightData<{
|
|
26
|
+
AuctionWorklets: typeof import("@paulirish/trace_engine/models/trace/handlers/AuctionWorkletsHandler.js");
|
|
27
|
+
Initiators: typeof import("@paulirish/trace_engine/models/trace/handlers/InitiatorsHandler.js");
|
|
28
|
+
LayoutShifts: typeof import("@paulirish/trace_engine/models/trace/handlers/LayoutShiftsHandler.js");
|
|
29
|
+
NetworkRequests: typeof import("@paulirish/trace_engine/models/trace/handlers/NetworkRequestsHandler.js");
|
|
30
|
+
Renderer: typeof import("@paulirish/trace_engine/models/trace/handlers/RendererHandler.js");
|
|
31
|
+
Samples: typeof import("@paulirish/trace_engine/models/trace/handlers/SamplesHandler.js");
|
|
32
|
+
Screenshots: typeof import("@paulirish/trace_engine/models/trace/handlers/ScreenshotsHandler.js");
|
|
33
|
+
PageLoadMetrics: typeof import("@paulirish/trace_engine/models/trace/handlers/PageLoadMetricsHandler.js");
|
|
34
|
+
}>>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=navigation-insights.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {makeComputedArtifact} from './computed-artifact.js';
|
|
8
|
+
import {ProcessedTrace} from './processed-trace.js';
|
|
9
|
+
import {TraceEngineResult} from './trace-engine-result.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @fileoverview Gets insights from the shared trace engine for the navigation audited by Lighthouse.
|
|
13
|
+
* Only usable in navigation mode.
|
|
14
|
+
*/
|
|
15
|
+
class NavigationInsights {
|
|
16
|
+
/**
|
|
17
|
+
* @param {LH.Trace} trace
|
|
18
|
+
* @param {LH.Artifacts.ComputedContext} context
|
|
19
|
+
*/
|
|
20
|
+
static async compute_(trace, context) {
|
|
21
|
+
const processedTrace = await ProcessedTrace.request(trace, context);
|
|
22
|
+
const traceEngineResult = await TraceEngineResult.request({trace}, context);
|
|
23
|
+
|
|
24
|
+
const navigationId = processedTrace.timeOriginEvt.args.data?.navigationId;
|
|
25
|
+
if (!navigationId) throw new Error('No navigationId found');
|
|
26
|
+
|
|
27
|
+
const navInsights = traceEngineResult.insights.get(navigationId);
|
|
28
|
+
if (!navInsights) throw new Error('No navigations insights found');
|
|
29
|
+
|
|
30
|
+
return navInsights;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const NavigationInsightsComputed = makeComputedArtifact(NavigationInsights, null);
|
|
35
|
+
export {NavigationInsightsComputed as NavigationInsights};
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
export { TraceEngineResultComputed as TraceEngineResult };
|
|
2
|
+
export type EnabledHandlers = typeof ENABLED_HANDLERS;
|
|
2
3
|
declare const TraceEngineResultComputed: typeof TraceEngineResult & {
|
|
3
4
|
request: (dependencies: {
|
|
4
5
|
trace: LH.Trace;
|
|
5
|
-
}, context:
|
|
6
|
+
}, context: LH.Util.ImmutableObject<{
|
|
6
7
|
computedCache: Map<string, import("../lib/arbitrary-equality-map.js").ArbitraryEqualityMap>;
|
|
7
|
-
}>) => Promise<
|
|
8
|
+
}>) => Promise<LH.Artifacts.TraceEngineResult>;
|
|
8
9
|
};
|
|
10
|
+
declare namespace ENABLED_HANDLERS {
|
|
11
|
+
const AuctionWorklets: typeof import("@paulirish/trace_engine/models/trace/handlers/AuctionWorkletsHandler.js");
|
|
12
|
+
const Initiators: typeof import("@paulirish/trace_engine/models/trace/handlers/InitiatorsHandler.js");
|
|
13
|
+
const LayoutShifts: typeof import("@paulirish/trace_engine/models/trace/handlers/LayoutShiftsHandler.js");
|
|
14
|
+
const NetworkRequests: typeof import("@paulirish/trace_engine/models/trace/handlers/NetworkRequestsHandler.js");
|
|
15
|
+
const Renderer: typeof import("@paulirish/trace_engine/models/trace/handlers/RendererHandler.js");
|
|
16
|
+
const Samples: typeof import("@paulirish/trace_engine/models/trace/handlers/SamplesHandler.js");
|
|
17
|
+
const Screenshots: typeof import("@paulirish/trace_engine/models/trace/handlers/ScreenshotsHandler.js");
|
|
18
|
+
const PageLoadMetrics: typeof import("@paulirish/trace_engine/models/trace/handlers/PageLoadMetricsHandler.js");
|
|
19
|
+
}
|
|
9
20
|
/**
|
|
10
21
|
* @fileoverview Processes trace with the shared trace engine.
|
|
11
22
|
*/
|
|
12
23
|
declare class TraceEngineResult {
|
|
13
24
|
/**
|
|
14
25
|
* @param {LH.TraceEvent[]} traceEvents
|
|
26
|
+
* @return {Promise<LH.Artifacts.TraceEngineResult>}
|
|
15
27
|
*/
|
|
16
|
-
static runTraceEngine(traceEvents: LH.TraceEvent[]): Promise<
|
|
28
|
+
static runTraceEngine(traceEvents: LH.TraceEvent[]): Promise<LH.Artifacts.TraceEngineResult>;
|
|
17
29
|
/**
|
|
18
30
|
* @param {{trace: LH.Trace}} data
|
|
19
31
|
* @param {LH.Artifacts.ComputedContext} context
|
|
@@ -23,4 +35,5 @@ declare class TraceEngineResult {
|
|
|
23
35
|
trace: LH.Trace;
|
|
24
36
|
}, context: LH.Artifacts.ComputedContext): Promise<LH.Artifacts.TraceEngineResult>;
|
|
25
37
|
}
|
|
38
|
+
import * as LH from '../../types/lh.js';
|
|
26
39
|
//# sourceMappingURL=trace-engine-result.d.ts.map
|
|
@@ -8,6 +8,20 @@ import * as TraceEngine from '../lib/trace-engine.js';
|
|
|
8
8
|
import {makeComputedArtifact} from './computed-artifact.js';
|
|
9
9
|
import {CumulativeLayoutShift} from './metrics/cumulative-layout-shift.js';
|
|
10
10
|
import {ProcessedTrace} from './processed-trace.js';
|
|
11
|
+
import * as LH from '../../types/lh.js';
|
|
12
|
+
|
|
13
|
+
/** @typedef {typeof ENABLED_HANDLERS} EnabledHandlers */
|
|
14
|
+
|
|
15
|
+
const ENABLED_HANDLERS = {
|
|
16
|
+
AuctionWorklets: TraceEngine.TraceHandlers.AuctionWorklets,
|
|
17
|
+
Initiators: TraceEngine.TraceHandlers.Initiators,
|
|
18
|
+
LayoutShifts: TraceEngine.TraceHandlers.LayoutShifts,
|
|
19
|
+
NetworkRequests: TraceEngine.TraceHandlers.NetworkRequests,
|
|
20
|
+
Renderer: TraceEngine.TraceHandlers.Renderer,
|
|
21
|
+
Samples: TraceEngine.TraceHandlers.Samples,
|
|
22
|
+
Screenshots: TraceEngine.TraceHandlers.Screenshots,
|
|
23
|
+
PageLoadMetrics: TraceEngine.TraceHandlers.PageLoadMetrics,
|
|
24
|
+
};
|
|
11
25
|
|
|
12
26
|
/**
|
|
13
27
|
* @fileoverview Processes trace with the shared trace engine.
|
|
@@ -15,24 +29,18 @@ import {ProcessedTrace} from './processed-trace.js';
|
|
|
15
29
|
class TraceEngineResult {
|
|
16
30
|
/**
|
|
17
31
|
* @param {LH.TraceEvent[]} traceEvents
|
|
32
|
+
* @return {Promise<LH.Artifacts.TraceEngineResult>}
|
|
18
33
|
*/
|
|
19
34
|
static async runTraceEngine(traceEvents) {
|
|
20
|
-
const engine = new TraceEngine.TraceProcessor(
|
|
21
|
-
AuctionWorklets: TraceEngine.TraceHandlers.AuctionWorklets,
|
|
22
|
-
Initiators: TraceEngine.TraceHandlers.Initiators,
|
|
23
|
-
LayoutShifts: TraceEngine.TraceHandlers.LayoutShifts,
|
|
24
|
-
NetworkRequests: TraceEngine.TraceHandlers.NetworkRequests,
|
|
25
|
-
Renderer: TraceEngine.TraceHandlers.Renderer,
|
|
26
|
-
Samples: TraceEngine.TraceHandlers.Samples,
|
|
27
|
-
Screenshots: TraceEngine.TraceHandlers.Screenshots,
|
|
28
|
-
});
|
|
35
|
+
const engine = new TraceEngine.TraceProcessor(ENABLED_HANDLERS);
|
|
29
36
|
// eslint-disable-next-line max-len
|
|
30
37
|
await engine.parse(/** @type {import('@paulirish/trace_engine').Types.TraceEvents.TraceEventData[]} */ (
|
|
31
38
|
traceEvents
|
|
32
39
|
));
|
|
33
40
|
// TODO: use TraceEngine.TraceProcessor.createWithAllHandlers above.
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
if (!engine.traceParsedData) throw new Error('No data');
|
|
42
|
+
if (!engine.insights) throw new Error('No insights');
|
|
43
|
+
return {data: engine.traceParsedData, insights: engine.insights};
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
/**
|
|
@@ -67,9 +75,6 @@ class TraceEngineResult {
|
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
const result = await TraceEngineResult.runTraceEngine(traceEvents);
|
|
70
|
-
if (!result) {
|
|
71
|
-
throw new Error('null trace engine result');
|
|
72
|
-
}
|
|
73
78
|
return result;
|
|
74
79
|
}
|
|
75
80
|
}
|
|
@@ -137,7 +137,6 @@ const defaultConfig = {
|
|
|
137
137
|
{id: 'Scripts', gatherer: 'scripts'},
|
|
138
138
|
{id: 'SourceMaps', gatherer: 'source-maps'},
|
|
139
139
|
{id: 'Stacks', gatherer: 'stacks'},
|
|
140
|
-
{id: 'TagsBlockingFirstPaint', gatherer: 'dobetterweb/tags-blocking-first-paint'},
|
|
141
140
|
{id: 'TraceElements', gatherer: 'trace-elements'},
|
|
142
141
|
{id: 'ViewportDimensions', gatherer: 'viewport-dimensions'},
|
|
143
142
|
|
package/core/config/filters.js
CHANGED
|
@@ -3,10 +3,10 @@ declare class RootCauses extends BaseGatherer {
|
|
|
3
3
|
static symbol: symbol;
|
|
4
4
|
/**
|
|
5
5
|
* @param {LH.Gatherer.Driver} driver
|
|
6
|
-
* @param {LH.Artifacts.TraceEngineResult}
|
|
6
|
+
* @param {LH.Artifacts.TraceEngineResult['data']} traceParsedData
|
|
7
7
|
* @return {Promise<LH.Artifacts.TraceEngineRootCauses>}
|
|
8
8
|
*/
|
|
9
|
-
static runRootCauseAnalysis(driver: LH.Gatherer.Driver,
|
|
9
|
+
static runRootCauseAnalysis(driver: LH.Gatherer.Driver, traceParsedData: LH.Artifacts.TraceEngineResult['data']): Promise<LH.Artifacts.TraceEngineRootCauses>;
|
|
10
10
|
/** @type {LH.Gatherer.GathererMeta<'Trace'>} */
|
|
11
11
|
meta: LH.Gatherer.GathererMeta<'Trace'>;
|
|
12
12
|
/**
|
|
@@ -21,10 +21,10 @@ class RootCauses extends BaseGatherer {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* @param {LH.Gatherer.Driver} driver
|
|
24
|
-
* @param {LH.Artifacts.TraceEngineResult}
|
|
24
|
+
* @param {LH.Artifacts.TraceEngineResult['data']} traceParsedData
|
|
25
25
|
* @return {Promise<LH.Artifacts.TraceEngineRootCauses>}
|
|
26
26
|
*/
|
|
27
|
-
static async runRootCauseAnalysis(driver,
|
|
27
|
+
static async runRootCauseAnalysis(driver, traceParsedData) {
|
|
28
28
|
await driver.defaultSession.sendCommand('DOM.enable');
|
|
29
29
|
await driver.defaultSession.sendCommand('CSS.enable');
|
|
30
30
|
|
|
@@ -112,9 +112,10 @@ class RootCauses extends BaseGatherer {
|
|
|
112
112
|
layoutShifts: {},
|
|
113
113
|
};
|
|
114
114
|
const rootCausesEngine = new TraceEngine.RootCauses(protocolInterface);
|
|
115
|
-
const layoutShiftEvents =
|
|
115
|
+
const layoutShiftEvents = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);
|
|
116
116
|
for (const event of layoutShiftEvents) {
|
|
117
|
-
|
|
117
|
+
// @ts-expect-error The data we do get in the trace processor is still enough here
|
|
118
|
+
const r = await rootCausesEngine.layoutShifts.rootCausesForEvent(traceParsedData, event);
|
|
118
119
|
if (!r) continue;
|
|
119
120
|
|
|
120
121
|
for (const cause of r.fontChanges) {
|
|
@@ -137,7 +138,7 @@ class RootCauses extends BaseGatherer {
|
|
|
137
138
|
async getArtifact(context) {
|
|
138
139
|
const trace = context.dependencies.Trace;
|
|
139
140
|
const traceEngineResult = await TraceEngineResult.request({trace}, context);
|
|
140
|
-
return RootCauses.runRootCauseAnalysis(context.driver, traceEngineResult);
|
|
141
|
+
return RootCauses.runRootCauseAnalysis(context.driver, traceEngineResult.data);
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
|
|
@@ -25,12 +25,12 @@ declare class TraceElements extends BaseGatherer {
|
|
|
25
25
|
* that may have caused the shift.
|
|
26
26
|
*
|
|
27
27
|
* @param {LH.Trace} trace
|
|
28
|
-
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
|
|
28
|
+
* @param {LH.Artifacts.TraceEngineResult['data']} traceEngineResult
|
|
29
29
|
* @param {LH.Artifacts.TraceEngineRootCauses} rootCauses
|
|
30
30
|
* @param {LH.Gatherer.Context} context
|
|
31
31
|
* @return {Promise<Array<{nodeId: number}>>}
|
|
32
32
|
*/
|
|
33
|
-
static getTopLayoutShifts(trace: LH.Trace, traceEngineResult: LH.Artifacts.TraceEngineResult, rootCauses: LH.Artifacts.TraceEngineRootCauses, context: LH.Gatherer.Context): Promise<Array<{
|
|
33
|
+
static getTopLayoutShifts(trace: LH.Trace, traceEngineResult: LH.Artifacts.TraceEngineResult['data'], rootCauses: LH.Artifacts.TraceEngineRootCauses, context: LH.Gatherer.Context): Promise<Array<{
|
|
34
34
|
nodeId: number;
|
|
35
35
|
}>>;
|
|
36
36
|
/**
|
|
@@ -122,7 +122,7 @@ class TraceElements extends BaseGatherer {
|
|
|
122
122
|
* that may have caused the shift.
|
|
123
123
|
*
|
|
124
124
|
* @param {LH.Trace} trace
|
|
125
|
-
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
|
|
125
|
+
* @param {LH.Artifacts.TraceEngineResult['data']} traceEngineResult
|
|
126
126
|
* @param {LH.Artifacts.TraceEngineRootCauses} rootCauses
|
|
127
127
|
* @param {LH.Gatherer.Context} context
|
|
128
128
|
* @return {Promise<Array<{nodeId: number}>>}
|
|
@@ -322,7 +322,7 @@ class TraceElements extends BaseGatherer {
|
|
|
322
322
|
|
|
323
323
|
const lcpNodeData = await TraceElements.getLcpElement(trace, context);
|
|
324
324
|
const shiftsData = await TraceElements.getTopLayoutShifts(
|
|
325
|
-
trace, traceEngineResult, rootCauses, context);
|
|
325
|
+
trace, traceEngineResult.data, rootCauses, context);
|
|
326
326
|
const animatedElementData = await this.getAnimatedElements(mainThreadEvents);
|
|
327
327
|
const responsivenessElementData = await TraceElements.getResponsivenessElement(trace, context);
|
|
328
328
|
|
|
@@ -6,11 +6,17 @@ export class CPUNode<T = any> extends BaseNode<T> {
|
|
|
6
6
|
/**
|
|
7
7
|
* @param {LH.TraceEvent} parentEvent
|
|
8
8
|
* @param {LH.TraceEvent[]=} childEvents
|
|
9
|
+
* @param {number=} correctedEndTs
|
|
9
10
|
*/
|
|
10
|
-
constructor(parentEvent: LH.TraceEvent, childEvents?: LH.TraceEvent[] | undefined);
|
|
11
|
+
constructor(parentEvent: LH.TraceEvent, childEvents?: LH.TraceEvent[] | undefined, correctedEndTs?: number | undefined);
|
|
11
12
|
_event: LH.TraceEvent;
|
|
12
13
|
_childEvents: LH.TraceEvent[];
|
|
14
|
+
_correctedEndTs: number | undefined;
|
|
13
15
|
get type(): "cpu";
|
|
16
|
+
/**
|
|
17
|
+
* @return {number}
|
|
18
|
+
*/
|
|
19
|
+
get duration(): number;
|
|
14
20
|
/**
|
|
15
21
|
* @return {LH.TraceEvent}
|
|
16
22
|
*/
|
|
@@ -15,13 +15,15 @@ class CPUNode extends BaseNode {
|
|
|
15
15
|
/**
|
|
16
16
|
* @param {LH.TraceEvent} parentEvent
|
|
17
17
|
* @param {LH.TraceEvent[]=} childEvents
|
|
18
|
+
* @param {number=} correctedEndTs
|
|
18
19
|
*/
|
|
19
|
-
constructor(parentEvent, childEvents = []) {
|
|
20
|
+
constructor(parentEvent, childEvents = [], correctedEndTs) {
|
|
20
21
|
const nodeId = `${parentEvent.tid}.${parentEvent.ts}`;
|
|
21
22
|
super(nodeId);
|
|
22
23
|
|
|
23
24
|
this._event = parentEvent;
|
|
24
25
|
this._childEvents = childEvents;
|
|
26
|
+
this._correctedEndTs = correctedEndTs;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
get type() {
|
|
@@ -39,9 +41,17 @@ class CPUNode extends BaseNode {
|
|
|
39
41
|
* @return {number}
|
|
40
42
|
*/
|
|
41
43
|
get endTime() {
|
|
44
|
+
if (this._correctedEndTs) return this._correctedEndTs;
|
|
42
45
|
return this._event.ts + this._event.dur;
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @return {number}
|
|
50
|
+
*/
|
|
51
|
+
get duration() {
|
|
52
|
+
return this.endTime - this.startTime;
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
/**
|
|
46
56
|
* @return {LH.TraceEvent}
|
|
47
57
|
*/
|
|
@@ -83,7 +93,7 @@ class CPUNode extends BaseNode {
|
|
|
83
93
|
* @return {CPUNode}
|
|
84
94
|
*/
|
|
85
95
|
cloneWithoutRelationships() {
|
|
86
|
-
return new CPUNode(this._event, this._childEvents);
|
|
96
|
+
return new CPUNode(this._event, this._childEvents, this._correctedEndTs);
|
|
87
97
|
}
|
|
88
98
|
}
|
|
89
99
|
|