lighthouse 12.3.0-dev.20250205 → 12.3.0-dev.20250206
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/audit.d.ts +5 -0
- package/core/audits/audit.js +11 -0
- package/core/audits/insights/README.md +3 -0
- package/core/audits/insights/cls-culprits-insight.d.ts +11 -0
- package/core/audits/insights/cls-culprits-insight.js +52 -0
- package/core/audits/insights/document-latency-insight.d.ts +11 -0
- package/core/audits/insights/document-latency-insight.js +47 -0
- package/core/audits/insights/dom-size-insight.d.ts +11 -0
- package/core/audits/insights/dom-size-insight.js +84 -0
- package/core/audits/insights/font-display-insight.d.ts +11 -0
- package/core/audits/insights/font-display-insight.js +52 -0
- package/core/audits/insights/forced-reflow-insight.d.ts +11 -0
- package/core/audits/insights/forced-reflow-insight.js +52 -0
- package/core/audits/insights/image-delivery-insight.d.ts +11 -0
- package/core/audits/insights/image-delivery-insight.js +52 -0
- package/core/audits/insights/insight-audit.d.ts +16 -0
- package/core/audits/insights/insight-audit.js +88 -0
- package/core/audits/insights/interaction-to-next-paint-insight.d.ts +11 -0
- package/core/audits/insights/interaction-to-next-paint-insight.js +52 -0
- package/core/audits/insights/lcp-discovery-insight.d.ts +11 -0
- package/core/audits/insights/lcp-discovery-insight.js +47 -0
- package/core/audits/insights/lcp-phases-insight.d.ts +11 -0
- package/core/audits/insights/lcp-phases-insight.js +52 -0
- package/core/audits/insights/long-critical-network-tree-insight.d.ts +11 -0
- package/core/audits/insights/long-critical-network-tree-insight.js +52 -0
- package/core/audits/insights/render-blocking-insight.d.ts +11 -0
- package/core/audits/insights/render-blocking-insight.js +56 -0
- package/core/audits/insights/slow-css-selector-insight.d.ts +11 -0
- package/core/audits/insights/slow-css-selector-insight.js +52 -0
- package/core/audits/insights/third-parties-insight.d.ts +11 -0
- package/core/audits/insights/third-parties-insight.js +52 -0
- package/core/audits/insights/viewport-insight.d.ts +11 -0
- package/core/audits/insights/viewport-insight.js +53 -0
- package/core/computed/metrics/lantern-metric.js +5 -1
- package/core/computed/trace-engine-result.d.ts +0 -4
- package/core/computed/trace-engine-result.js +0 -26
- package/core/config/default-config.js +35 -0
- package/core/gather/gatherers/trace-elements.d.ts +8 -0
- package/core/gather/gatherers/trace-elements.js +71 -1
- package/core/runner.js +2 -0
- package/dist/report/bundle.esm.js +38 -3
- package/dist/report/flow.js +40 -5
- package/dist/report/standalone.js +38 -3
- package/package.json +4 -3
- package/report/assets/styles.css +35 -0
- package/report/renderer/components.js +1 -1
- package/report/renderer/details-renderer.d.ts +5 -0
- package/report/renderer/details-renderer.js +21 -0
- package/report/renderer/performance-category-renderer.js +24 -9
- package/shared/localization/locales/en-US.json +213 -0
- package/shared/localization/locales/en-XL.json +213 -0
- package/types/artifacts.d.ts +1 -1
- package/types/lhr/audit-details.d.ts +6 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/LCPDiscovery.js';
|
|
8
|
+
|
|
9
|
+
import {Audit} from '../audit.js';
|
|
10
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
+
import {adaptInsightToAuditProduct} from './insight-audit.js';
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line max-len
|
|
14
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/LCPDiscovery.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
class LCPDiscoveryInsight extends Audit {
|
|
17
|
+
/**
|
|
18
|
+
* @return {LH.Audit.Meta}
|
|
19
|
+
*/
|
|
20
|
+
static get meta() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'lcp-discovery-insight',
|
|
23
|
+
title: str_(UIStrings.title),
|
|
24
|
+
failureTitle: str_(UIStrings.title),
|
|
25
|
+
description: str_(UIStrings.description),
|
|
26
|
+
guidanceLevel: 3,
|
|
27
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {LH.Artifacts} artifacts
|
|
33
|
+
* @param {LH.Audit.Context} context
|
|
34
|
+
* @return {Promise<LH.Audit.Product>}
|
|
35
|
+
*/
|
|
36
|
+
static async audit(artifacts, context) {
|
|
37
|
+
return adaptInsightToAuditProduct(artifacts, context, 'LCPDiscovery', (insight) => {
|
|
38
|
+
if (!insight.checklist) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return Audit.makeChecklistDetails(insight.checklist);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default LCPDiscoveryInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default LCPPhasesInsight;
|
|
2
|
+
declare class LCPPhasesInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Artifacts} artifacts
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
7
|
+
*/
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
9
|
+
}
|
|
10
|
+
import { Audit } from '../audit.js';
|
|
11
|
+
//# sourceMappingURL=lcp-phases-insight.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */ // TODO: remove once implemented.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2025 Google LLC
|
|
6
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/LCPPhases.js';
|
|
10
|
+
|
|
11
|
+
import {Audit} from '../audit.js';
|
|
12
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
13
|
+
import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line max-len
|
|
16
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/LCPPhases.js', UIStrings);
|
|
17
|
+
|
|
18
|
+
class LCPPhasesInsight extends Audit {
|
|
19
|
+
/**
|
|
20
|
+
* @return {LH.Audit.Meta}
|
|
21
|
+
*/
|
|
22
|
+
static get meta() {
|
|
23
|
+
return {
|
|
24
|
+
id: 'lcp-phases-insight',
|
|
25
|
+
title: str_(UIStrings.title),
|
|
26
|
+
failureTitle: str_(UIStrings.title),
|
|
27
|
+
description: str_(UIStrings.description),
|
|
28
|
+
guidanceLevel: 3,
|
|
29
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {LH.Artifacts} artifacts
|
|
35
|
+
* @param {LH.Audit.Context} context
|
|
36
|
+
* @return {Promise<LH.Audit.Product>}
|
|
37
|
+
*/
|
|
38
|
+
static async audit(artifacts, context) {
|
|
39
|
+
// TODO: implement.
|
|
40
|
+
return adaptInsightToAuditProduct(artifacts, context, 'LCPPhases', (insight) => {
|
|
41
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
42
|
+
const headings = [
|
|
43
|
+
];
|
|
44
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
45
|
+
const items = [
|
|
46
|
+
];
|
|
47
|
+
return Audit.makeTableDetails(headings, items);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default LCPPhasesInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default LongCriticalNetworkTreeInsight;
|
|
2
|
+
declare class LongCriticalNetworkTreeInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Artifacts} artifacts
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
7
|
+
*/
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
9
|
+
}
|
|
10
|
+
import { Audit } from '../audit.js';
|
|
11
|
+
//# sourceMappingURL=long-critical-network-tree-insight.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */ // TODO: remove once implemented.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2025 Google LLC
|
|
6
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/LongCriticalNetworkTree.js';
|
|
10
|
+
|
|
11
|
+
import {Audit} from '../audit.js';
|
|
12
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
13
|
+
import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line max-len
|
|
16
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/LongCriticalNetworkTree.js', UIStrings);
|
|
17
|
+
|
|
18
|
+
class LongCriticalNetworkTreeInsight extends Audit {
|
|
19
|
+
/**
|
|
20
|
+
* @return {LH.Audit.Meta}
|
|
21
|
+
*/
|
|
22
|
+
static get meta() {
|
|
23
|
+
return {
|
|
24
|
+
id: 'long-critical-network-tree-insight',
|
|
25
|
+
title: str_(UIStrings.title),
|
|
26
|
+
failureTitle: str_(UIStrings.title),
|
|
27
|
+
description: str_(UIStrings.description),
|
|
28
|
+
guidanceLevel: 3,
|
|
29
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {LH.Artifacts} artifacts
|
|
35
|
+
* @param {LH.Audit.Context} context
|
|
36
|
+
* @return {Promise<LH.Audit.Product>}
|
|
37
|
+
*/
|
|
38
|
+
static async audit(artifacts, context) {
|
|
39
|
+
// TODO: implement.
|
|
40
|
+
return adaptInsightToAuditProduct(artifacts, context, 'LongCriticalNetworkTree', (insight) => {
|
|
41
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
42
|
+
const headings = [
|
|
43
|
+
];
|
|
44
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
45
|
+
const items = [
|
|
46
|
+
];
|
|
47
|
+
return Audit.makeTableDetails(headings, items);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default LongCriticalNetworkTreeInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default RenderBlockingInsight;
|
|
2
|
+
declare class RenderBlockingInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Artifacts} artifacts
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
7
|
+
*/
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
9
|
+
}
|
|
10
|
+
import { Audit } from '../audit.js';
|
|
11
|
+
//# sourceMappingURL=render-blocking-insight.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/RenderBlocking.js';
|
|
8
|
+
|
|
9
|
+
import {Audit} from '../audit.js';
|
|
10
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
+
import {adaptInsightToAuditProduct} from './insight-audit.js';
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line max-len
|
|
14
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/RenderBlocking.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
class RenderBlockingInsight extends Audit {
|
|
17
|
+
/**
|
|
18
|
+
* @return {LH.Audit.Meta}
|
|
19
|
+
*/
|
|
20
|
+
static get meta() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'render-blocking-insight',
|
|
23
|
+
title: str_(UIStrings.title),
|
|
24
|
+
failureTitle: str_(UIStrings.title),
|
|
25
|
+
description: str_(UIStrings.description),
|
|
26
|
+
guidanceLevel: 3,
|
|
27
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {LH.Artifacts} artifacts
|
|
33
|
+
* @param {LH.Audit.Context} context
|
|
34
|
+
* @return {Promise<LH.Audit.Product>}
|
|
35
|
+
*/
|
|
36
|
+
static async audit(artifacts, context) {
|
|
37
|
+
// TODO: show UIStrings.noRenderBlocking if nothing was blocking?
|
|
38
|
+
return adaptInsightToAuditProduct(artifacts, context, 'RenderBlocking', (insight) => {
|
|
39
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
40
|
+
const headings = [
|
|
41
|
+
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
42
|
+
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnTransferSize)},
|
|
43
|
+
{key: 'wastedMs', valueType: 'timespanMs', label: str_(i18n.UIStrings.columnWastedMs)},
|
|
44
|
+
];
|
|
45
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
46
|
+
const items = insight.renderBlockingRequests.map(request => ({
|
|
47
|
+
url: request.args.data.url,
|
|
48
|
+
totalBytes: request.args.data.encodedDataLength,
|
|
49
|
+
wastedMs: insight.requestIdToWastedMs?.get(request.args.data.requestId),
|
|
50
|
+
}));
|
|
51
|
+
return Audit.makeTableDetails(headings, items);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default RenderBlockingInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default SlowCSSSelectorInsight;
|
|
2
|
+
declare class SlowCSSSelectorInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Artifacts} artifacts
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
7
|
+
*/
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
9
|
+
}
|
|
10
|
+
import { Audit } from '../audit.js';
|
|
11
|
+
//# sourceMappingURL=slow-css-selector-insight.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */ // TODO: remove once implemented.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2025 Google LLC
|
|
6
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/SlowCSSSelector.js';
|
|
10
|
+
|
|
11
|
+
import {Audit} from '../audit.js';
|
|
12
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
13
|
+
import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line max-len
|
|
16
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/SlowCSSSelector.js', UIStrings);
|
|
17
|
+
|
|
18
|
+
class SlowCSSSelectorInsight extends Audit {
|
|
19
|
+
/**
|
|
20
|
+
* @return {LH.Audit.Meta}
|
|
21
|
+
*/
|
|
22
|
+
static get meta() {
|
|
23
|
+
return {
|
|
24
|
+
id: 'slow-css-selector-insight',
|
|
25
|
+
title: str_(UIStrings.title),
|
|
26
|
+
failureTitle: str_(UIStrings.title),
|
|
27
|
+
description: str_(UIStrings.description),
|
|
28
|
+
guidanceLevel: 3,
|
|
29
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {LH.Artifacts} artifacts
|
|
35
|
+
* @param {LH.Audit.Context} context
|
|
36
|
+
* @return {Promise<LH.Audit.Product>}
|
|
37
|
+
*/
|
|
38
|
+
static async audit(artifacts, context) {
|
|
39
|
+
// TODO: implement.
|
|
40
|
+
return adaptInsightToAuditProduct(artifacts, context, 'SlowCSSSelector', (insight) => {
|
|
41
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
42
|
+
const headings = [
|
|
43
|
+
];
|
|
44
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
45
|
+
const items = [
|
|
46
|
+
];
|
|
47
|
+
return Audit.makeTableDetails(headings, items);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default SlowCSSSelectorInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default ThirdPartiesInsight;
|
|
2
|
+
declare class ThirdPartiesInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Artifacts} artifacts
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
7
|
+
*/
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
9
|
+
}
|
|
10
|
+
import { Audit } from '../audit.js';
|
|
11
|
+
//# sourceMappingURL=third-parties-insight.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */ // TODO: remove once implemented.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2025 Google LLC
|
|
6
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/ThirdParties.js';
|
|
10
|
+
|
|
11
|
+
import {Audit} from '../audit.js';
|
|
12
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
13
|
+
import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line max-len
|
|
16
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/ThirdParties.js', UIStrings);
|
|
17
|
+
|
|
18
|
+
class ThirdPartiesInsight extends Audit {
|
|
19
|
+
/**
|
|
20
|
+
* @return {LH.Audit.Meta}
|
|
21
|
+
*/
|
|
22
|
+
static get meta() {
|
|
23
|
+
return {
|
|
24
|
+
id: 'third-parties-insight',
|
|
25
|
+
title: str_(UIStrings.title),
|
|
26
|
+
failureTitle: str_(UIStrings.title),
|
|
27
|
+
description: str_(UIStrings.description),
|
|
28
|
+
guidanceLevel: 3,
|
|
29
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {LH.Artifacts} artifacts
|
|
35
|
+
* @param {LH.Audit.Context} context
|
|
36
|
+
* @return {Promise<LH.Audit.Product>}
|
|
37
|
+
*/
|
|
38
|
+
static async audit(artifacts, context) {
|
|
39
|
+
// TODO: implement.
|
|
40
|
+
return adaptInsightToAuditProduct(artifacts, context, 'ThirdParties', (insight) => {
|
|
41
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
42
|
+
const headings = [
|
|
43
|
+
];
|
|
44
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
45
|
+
const items = [
|
|
46
|
+
];
|
|
47
|
+
return Audit.makeTableDetails(headings, items);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default ThirdPartiesInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default ViewportInsight;
|
|
2
|
+
declare class ViewportInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Artifacts} artifacts
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
7
|
+
*/
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
9
|
+
}
|
|
10
|
+
import { Audit } from '../audit.js';
|
|
11
|
+
//# sourceMappingURL=viewport-insight.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/Viewport.js';
|
|
8
|
+
|
|
9
|
+
import {Audit} from '../audit.js';
|
|
10
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
+
import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line max-len
|
|
14
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/Viewport.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
class ViewportInsight extends Audit {
|
|
17
|
+
/**
|
|
18
|
+
* @return {LH.Audit.Meta}
|
|
19
|
+
*/
|
|
20
|
+
static get meta() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'viewport-insight',
|
|
23
|
+
title: str_(UIStrings.title),
|
|
24
|
+
failureTitle: str_(UIStrings.title),
|
|
25
|
+
description: str_(UIStrings.description),
|
|
26
|
+
guidanceLevel: 3,
|
|
27
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {LH.Artifacts} artifacts
|
|
33
|
+
* @param {LH.Audit.Context} context
|
|
34
|
+
* @return {Promise<LH.Audit.Product>}
|
|
35
|
+
*/
|
|
36
|
+
static async audit(artifacts, context) {
|
|
37
|
+
return adaptInsightToAuditProduct(artifacts, context, 'Viewport', (insight) => {
|
|
38
|
+
const nodeId = insight.viewportEvent?.args.data.node_id;
|
|
39
|
+
|
|
40
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
41
|
+
const headings = [
|
|
42
|
+
{key: 'node', valueType: 'node', label: ''},
|
|
43
|
+
];
|
|
44
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
45
|
+
const items = [
|
|
46
|
+
{node: makeNodeItemForNodeId(artifacts.TraceElements, nodeId)},
|
|
47
|
+
];
|
|
48
|
+
return Audit.makeTableDetails(headings, items);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default ViewportInsight;
|
|
@@ -39,7 +39,11 @@ async function getComputationDataParamsFromTrace(data, context) {
|
|
|
39
39
|
const graph = await PageDependencyGraph.request({...data, fromTrace: true}, context);
|
|
40
40
|
const traceEngineResult = await TraceEngineResult.request(data, context);
|
|
41
41
|
const frameId = traceEngineResult.data.Meta.mainFrameId;
|
|
42
|
-
const navigationId = traceEngineResult.data.Meta.mainFrameNavigations[0].args.data
|
|
42
|
+
const navigationId = traceEngineResult.data.Meta.mainFrameNavigations[0].args.data?.navigationId;
|
|
43
|
+
if (!navigationId) {
|
|
44
|
+
throw new Error(`Lantern metrics could not be calculated due to missing navigation id`);
|
|
45
|
+
}
|
|
46
|
+
|
|
43
47
|
const processedNavigation = Lantern.TraceEngineComputationData.createProcessedNavigation(
|
|
44
48
|
traceEngineResult.data, frameId, navigationId);
|
|
45
49
|
const simulator = data.simulator || (await LoadSimulator.request(data, context));
|
|
@@ -13,10 +13,6 @@ declare class TraceEngineResult {
|
|
|
13
13
|
* @return {Promise<LH.Artifacts.TraceEngineResult>}
|
|
14
14
|
*/
|
|
15
15
|
static runTraceEngine(traceEvents: LH.TraceEvent[]): Promise<LH.Artifacts.TraceEngineResult>;
|
|
16
|
-
/**
|
|
17
|
-
* @param {import('@paulirish/trace_engine/models/trace/insights/types.js').TraceInsightSets} insightSets
|
|
18
|
-
*/
|
|
19
|
-
static localizeInsights(insightSets: import("@paulirish/trace_engine/models/trace/insights/types.js").TraceInsightSets): void;
|
|
20
16
|
/**
|
|
21
17
|
* @param {{trace: LH.Trace}} data
|
|
22
18
|
* @param {LH.Artifacts.ComputedContext} context
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as i18n from '../lib/i18n/i18n.js';
|
|
8
7
|
import * as TraceEngine from '../lib/trace-engine.js';
|
|
9
8
|
import {makeComputedArtifact} from './computed-artifact.js';
|
|
10
9
|
import {CumulativeLayoutShift} from './metrics/cumulative-layout-shift.js';
|
|
@@ -28,34 +27,9 @@ class TraceEngineResult {
|
|
|
28
27
|
), {});
|
|
29
28
|
if (!processor.parsedTrace) throw new Error('No data');
|
|
30
29
|
if (!processor.insights) throw new Error('No insights');
|
|
31
|
-
this.localizeInsights(processor.insights);
|
|
32
30
|
return {data: processor.parsedTrace, insights: processor.insights};
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
/**
|
|
36
|
-
* @param {import('@paulirish/trace_engine/models/trace/insights/types.js').TraceInsightSets} insightSets
|
|
37
|
-
*/
|
|
38
|
-
static localizeInsights(insightSets) {
|
|
39
|
-
for (const insightSet of insightSets.values()) {
|
|
40
|
-
for (const [name, model] of Object.entries(insightSet.model)) {
|
|
41
|
-
if (model instanceof Error) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const key = `node_modules/@paulirish/trace_engine/models/trace/insights/${name}.js`;
|
|
46
|
-
const str_ = i18n.createIcuMessageFn(key, {
|
|
47
|
-
title: model.title,
|
|
48
|
-
description: model.description,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// @ts-expect-error coerce to string, should be fine
|
|
52
|
-
model.title = str_(model.title);
|
|
53
|
-
// @ts-expect-error coerce to string, should be fine
|
|
54
|
-
model.description = str_(model.description);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
33
|
/**
|
|
60
34
|
* @param {{trace: LH.Trace}} data
|
|
61
35
|
* @param {LH.Artifacts.ComputedContext} context
|
|
@@ -15,6 +15,8 @@ const UIStrings = {
|
|
|
15
15
|
performanceCategoryTitle: 'Performance',
|
|
16
16
|
/** Title of the speed metrics section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. */
|
|
17
17
|
metricGroupTitle: 'Metrics',
|
|
18
|
+
/** Title of the insights section of the Performance category. Within this section are various insights to give developers tips on how to improve the performance of their page. */
|
|
19
|
+
insightGroupTitle: 'Insights',
|
|
18
20
|
/** Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage. */
|
|
19
21
|
firstPaintImprovementsGroupTitle: 'First Paint Improvements',
|
|
20
22
|
/** Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage. */
|
|
@@ -308,11 +310,28 @@ const defaultConfig = {
|
|
|
308
310
|
'seo/manual/structured-data',
|
|
309
311
|
'work-during-interaction',
|
|
310
312
|
'bf-cache',
|
|
313
|
+
'insights/cls-culprits-insight',
|
|
314
|
+
'insights/document-latency-insight',
|
|
315
|
+
'insights/dom-size-insight',
|
|
316
|
+
'insights/font-display-insight',
|
|
317
|
+
'insights/forced-reflow-insight',
|
|
318
|
+
'insights/image-delivery-insight',
|
|
319
|
+
'insights/interaction-to-next-paint-insight',
|
|
320
|
+
'insights/lcp-discovery-insight',
|
|
321
|
+
'insights/lcp-phases-insight',
|
|
322
|
+
'insights/long-critical-network-tree-insight',
|
|
323
|
+
'insights/render-blocking-insight',
|
|
324
|
+
'insights/slow-css-selector-insight',
|
|
325
|
+
'insights/third-parties-insight',
|
|
326
|
+
'insights/viewport-insight',
|
|
311
327
|
],
|
|
312
328
|
groups: {
|
|
313
329
|
'metrics': {
|
|
314
330
|
title: str_(UIStrings.metricGroupTitle),
|
|
315
331
|
},
|
|
332
|
+
'insights': {
|
|
333
|
+
title: str_(UIStrings.insightGroupTitle),
|
|
334
|
+
},
|
|
316
335
|
'diagnostics': {
|
|
317
336
|
title: str_(UIStrings.diagnosticsGroupTitle),
|
|
318
337
|
description: str_(UIStrings.diagnosticsGroupDescription),
|
|
@@ -388,6 +407,22 @@ const defaultConfig = {
|
|
|
388
407
|
{id: 'speed-index', weight: 10, group: 'metrics', acronym: 'SI'},
|
|
389
408
|
{id: 'interaction-to-next-paint', weight: 0, group: 'metrics', acronym: 'INP'},
|
|
390
409
|
|
|
410
|
+
// Insight audits.
|
|
411
|
+
{id: 'cls-culprits-insight', weight: 0, group: 'hidden'},
|
|
412
|
+
{id: 'document-latency-insight', weight: 0, group: 'hidden'},
|
|
413
|
+
{id: 'dom-size-insight', weight: 0, group: 'hidden'},
|
|
414
|
+
{id: 'font-display-insight', weight: 0, group: 'hidden'},
|
|
415
|
+
{id: 'forced-reflow-insight', weight: 0, group: 'hidden'},
|
|
416
|
+
{id: 'image-delivery-insight', weight: 0, group: 'hidden'},
|
|
417
|
+
{id: 'interaction-to-next-paint-insight', weight: 0, group: 'hidden'},
|
|
418
|
+
{id: 'lcp-discovery-insight', weight: 0, group: 'hidden'},
|
|
419
|
+
{id: 'lcp-phases-insight', weight: 0, group: 'hidden'},
|
|
420
|
+
{id: 'long-critical-network-tree-insight', weight: 0, group: 'hidden'},
|
|
421
|
+
{id: 'render-blocking-insight', weight: 0, group: 'hidden'},
|
|
422
|
+
{id: 'slow-css-selector-insight', weight: 0, group: 'hidden'},
|
|
423
|
+
{id: 'third-parties-insight', weight: 0, group: 'hidden'},
|
|
424
|
+
{id: 'viewport-insight', weight: 0, group: 'hidden'},
|
|
425
|
+
|
|
391
426
|
// These are our "invisible" metrics. Not displayed, but still in the LHR.
|
|
392
427
|
{id: 'interactive', weight: 0, group: 'hidden', acronym: 'TTI'},
|
|
393
428
|
{id: 'max-potential-fid', weight: 0, group: 'hidden'},
|
|
@@ -9,6 +9,14 @@ export type TraceElementData = {
|
|
|
9
9
|
type?: string;
|
|
10
10
|
};
|
|
11
11
|
declare class TraceElements extends BaseGatherer {
|
|
12
|
+
/**
|
|
13
|
+
* @param {LH.Artifacts.TraceEngineResult} traceEngineResult
|
|
14
|
+
* @param {string|undefined} navigationId
|
|
15
|
+
* @return {Promise<Array<{nodeId: number}>>}
|
|
16
|
+
*/
|
|
17
|
+
static getTraceEngineElements(traceEngineResult: LH.Artifacts.TraceEngineResult, navigationId: string | undefined): Promise<Array<{
|
|
18
|
+
nodeId: number;
|
|
19
|
+
}>>;
|
|
12
20
|
/**
|
|
13
21
|
* We want to a single representative node to represent the shift, so let's pick
|
|
14
22
|
* the one with the largest impact (size x distance moved).
|