lighthouse 12.3.0 → 12.4.0
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/cli/test/smokehouse/core-tests.js +4 -0
- package/core/audits/audit.d.ts +5 -0
- package/core/audits/audit.js +12 -0
- package/core/audits/bootup-time.js +0 -2
- package/core/audits/byte-efficiency/duplicated-javascript.d.ts +4 -5
- package/core/audits/byte-efficiency/duplicated-javascript.js +9 -5
- package/core/audits/byte-efficiency/legacy-javascript.d.ts +2 -2
- package/core/audits/byte-efficiency/legacy-javascript.js +17 -5
- package/core/audits/byte-efficiency/polyfill-graph-data.json +48 -49
- package/core/audits/byte-efficiency/total-byte-weight.js +0 -2
- package/core/audits/clickjacking-mitigation.d.ts +42 -0
- package/core/audits/clickjacking-mitigation.js +139 -0
- package/core/audits/dobetterweb/dom-size.js +0 -2
- package/core/audits/insights/README.md +3 -0
- package/core/audits/insights/cls-culprits-insight.d.ts +25 -0
- package/core/audits/insights/cls-culprits-insight.js +137 -0
- package/core/audits/insights/document-latency-insight.d.ts +11 -0
- package/core/audits/insights/document-latency-insight.js +48 -0
- package/core/audits/insights/dom-size-insight.d.ts +11 -0
- package/core/audits/insights/dom-size-insight.js +85 -0
- package/core/audits/insights/font-display-insight.d.ts +11 -0
- package/core/audits/insights/font-display-insight.js +53 -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 +83 -0
- package/core/audits/insights/insight-audit.d.ts +23 -0
- package/core/audits/insights/insight-audit.js +133 -0
- package/core/audits/insights/interaction-to-next-paint-insight.d.ts +11 -0
- package/core/audits/insights/interaction-to-next-paint-insight.js +71 -0
- package/core/audits/insights/lcp-discovery-insight.d.ts +11 -0
- package/core/audits/insights/lcp-discovery-insight.js +48 -0
- package/core/audits/insights/lcp-phases-insight.d.ts +16 -0
- package/core/audits/insights/lcp-phases-insight.js +87 -0
- package/core/audits/insights/long-critical-network-tree-insight.d.ts +11 -0
- package/core/audits/insights/long-critical-network-tree-insight.js +53 -0
- package/core/audits/insights/render-blocking-insight.d.ts +11 -0
- package/core/audits/insights/render-blocking-insight.js +57 -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 +28 -0
- package/core/audits/insights/third-parties-insight.js +90 -0
- package/core/audits/insights/viewport-insight.d.ts +11 -0
- package/core/audits/insights/viewport-insight.js +54 -0
- package/core/audits/layout-shifts.d.ts +0 -1
- package/core/audits/layout-shifts.js +18 -21
- package/core/audits/mainthread-work-breakdown.js +0 -2
- package/core/audits/seo/is-crawlable.d.ts +1 -0
- package/core/audits/server-response-time.js +0 -1
- package/core/computed/metrics/lantern-metric.js +5 -1
- package/core/computed/trace-engine-result.js +71 -17
- package/core/config/default-config.js +37 -1
- package/core/gather/gatherers/inspector-issues.js +3 -0
- package/core/gather/gatherers/trace-elements.d.ts +10 -2
- package/core/gather/gatherers/trace-elements.js +89 -12
- package/core/lib/bf-cache-strings.d.ts +7 -4
- package/core/lib/bf-cache-strings.js +174 -140
- package/core/lib/cdt/generated/ParsedURL.d.ts +1 -0
- package/core/lib/cdt/generated/ParsedURL.js +16 -4
- package/core/lib/cdt/generated/SourceMap.d.ts +32 -5
- package/core/lib/cdt/generated/SourceMap.js +192 -100
- package/core/lib/deprecations-strings.d.ts +78 -98
- package/core/lib/deprecations-strings.js +23 -41
- package/core/lib/i18n/i18n.d.ts +1 -0
- package/core/lib/i18n/i18n.js +2 -0
- package/core/lib/trace-engine.d.ts +1 -0
- package/core/lib/trace-engine.js +2 -0
- package/core/runner.js +2 -0
- package/dist/report/bundle.esm.js +196 -9
- package/dist/report/flow.js +197 -10
- package/dist/report/standalone.js +197 -10
- package/flow-report/src/i18n/i18n.d.ts +2 -0
- package/package.json +15 -13
- package/readme.md +3 -0
- package/report/assets/styles.css +179 -5
- package/report/assets/templates.html +14 -0
- package/report/renderer/components.js +9 -3
- package/report/renderer/details-renderer.d.ts +5 -0
- package/report/renderer/details-renderer.js +24 -0
- package/report/renderer/dom.d.ts +12 -1
- package/report/renderer/dom.js +26 -1
- package/report/renderer/i18n-formatter.d.ts +1 -1
- package/report/renderer/performance-category-renderer.d.ts +10 -0
- package/report/renderer/performance-category-renderer.js +81 -20
- package/report/renderer/report-utils.d.ts +1 -0
- package/report/renderer/report-utils.js +2 -0
- package/report/renderer/topbar-features.js +7 -0
- package/shared/localization/locales/ar-XB.json +74 -26
- package/shared/localization/locales/ar.json +76 -28
- package/shared/localization/locales/bg.json +74 -26
- package/shared/localization/locales/ca.json +74 -26
- package/shared/localization/locales/cs.json +74 -26
- package/shared/localization/locales/da.json +74 -26
- package/shared/localization/locales/de.json +75 -27
- package/shared/localization/locales/el.json +74 -26
- package/shared/localization/locales/en-GB.json +74 -26
- package/shared/localization/locales/en-US.json +288 -30
- package/shared/localization/locales/en-XA.json +48 -24
- package/shared/localization/locales/en-XL.json +288 -30
- package/shared/localization/locales/es-419.json +74 -26
- package/shared/localization/locales/es.json +74 -26
- package/shared/localization/locales/fi.json +74 -26
- package/shared/localization/locales/fil.json +75 -27
- package/shared/localization/locales/fr.json +74 -26
- package/shared/localization/locales/he.json +82 -34
- package/shared/localization/locales/hi.json +74 -26
- package/shared/localization/locales/hr.json +75 -27
- package/shared/localization/locales/hu.json +74 -26
- package/shared/localization/locales/id.json +74 -26
- package/shared/localization/locales/it.json +85 -37
- package/shared/localization/locales/ja.json +75 -27
- package/shared/localization/locales/ko.json +75 -27
- package/shared/localization/locales/lt.json +75 -27
- package/shared/localization/locales/lv.json +74 -26
- package/shared/localization/locales/nl.json +74 -26
- package/shared/localization/locales/no.json +75 -27
- package/shared/localization/locales/pl.json +74 -26
- package/shared/localization/locales/pt-PT.json +74 -26
- package/shared/localization/locales/pt.json +74 -26
- package/shared/localization/locales/ro.json +74 -26
- package/shared/localization/locales/ru.json +74 -26
- package/shared/localization/locales/sk.json +74 -26
- package/shared/localization/locales/sl.json +74 -26
- package/shared/localization/locales/sr-Latn.json +74 -26
- package/shared/localization/locales/sr.json +74 -26
- package/shared/localization/locales/sv.json +74 -26
- package/shared/localization/locales/ta.json +74 -26
- package/shared/localization/locales/te.json +74 -26
- package/shared/localization/locales/th.json +76 -28
- package/shared/localization/locales/tr.json +74 -26
- package/shared/localization/locales/uk.json +74 -26
- package/shared/localization/locales/vi.json +74 -26
- package/shared/localization/locales/zh-HK.json +75 -27
- package/shared/localization/locales/zh-TW.json +74 -26
- package/shared/localization/locales/zh.json +74 -26
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +3 -0
- package/types/artifacts.d.ts +5 -3
- package/types/audit.d.ts +2 -0
- package/types/lhr/audit-details.d.ts +13 -1
- package/types/lhr/audit-result.d.ts +2 -0
- package/core/gather/gatherers/root-causes.d.ts +0 -19
- package/core/gather/gatherers/root-causes.js +0 -144
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default InteractionToNextPaintInsight;
|
|
2
|
+
declare class InteractionToNextPaintInsight 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=interaction-to-next-paint-insight.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
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/InteractionToNextPaint.js';
|
|
8
|
+
|
|
9
|
+
import {Audit} from '../audit.js';
|
|
10
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
+
import {adaptInsightToAuditProduct, maybeMakeNodeElementTable} 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/InteractionToNextPaint.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
class InteractionToNextPaintInsight extends Audit {
|
|
17
|
+
/**
|
|
18
|
+
* @return {LH.Audit.Meta}
|
|
19
|
+
*/
|
|
20
|
+
static get meta() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'interaction-to-next-paint-insight',
|
|
23
|
+
title: str_(UIStrings.title),
|
|
24
|
+
failureTitle: str_(UIStrings.title),
|
|
25
|
+
description: str_(UIStrings.description),
|
|
26
|
+
guidanceLevel: 3,
|
|
27
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
28
|
+
replacesAudits: ['work-during-interaction'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {LH.Artifacts} artifacts
|
|
34
|
+
* @param {LH.Audit.Context} context
|
|
35
|
+
* @return {Promise<LH.Audit.Product>}
|
|
36
|
+
*/
|
|
37
|
+
static async audit(artifacts, context) {
|
|
38
|
+
return adaptInsightToAuditProduct(artifacts, context, 'InteractionToNextPaint', (insight) => {
|
|
39
|
+
const event = insight.longestInteractionEvent;
|
|
40
|
+
if (!event) {
|
|
41
|
+
// TODO: show UIStrings.noInteractions?
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
46
|
+
const headings = [
|
|
47
|
+
{key: 'label', valueType: 'text', label: str_(UIStrings.phase)},
|
|
48
|
+
{key: 'duration', valueType: 'ms', label: str_(i18n.UIStrings.columnDuration)},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
52
|
+
const items = [
|
|
53
|
+
/* eslint-disable max-len */
|
|
54
|
+
{phase: 'inputDelay', label: str_(UIStrings.inputDelay), duration: event.inputDelay / 1000},
|
|
55
|
+
{phase: 'processingDuration', label: str_(UIStrings.processingDuration), duration: event.mainThreadHandling / 1000},
|
|
56
|
+
{phase: 'presentationDelay', label: str_(UIStrings.presentationDelay), duration: event.presentationDelay / 1000},
|
|
57
|
+
/* eslint-enable max-len */
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
return Audit.makeListDetails([
|
|
61
|
+
maybeMakeNodeElementTable(
|
|
62
|
+
artifacts.TraceElements,
|
|
63
|
+
event.args.data.beginEvent.args.data.nodeId,
|
|
64
|
+
str_(i18n.UIStrings.columnElement)),
|
|
65
|
+
Audit.makeTableDetails(headings, items),
|
|
66
|
+
].filter(table => !!table));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default InteractionToNextPaintInsight;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default LCPDiscoveryInsight;
|
|
2
|
+
declare class LCPDiscoveryInsight 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-discovery-insight.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
replacesAudits: ['prioritize-lcp-image', 'lcp-lazy-loaded'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {LH.Artifacts} artifacts
|
|
34
|
+
* @param {LH.Audit.Context} context
|
|
35
|
+
* @return {Promise<LH.Audit.Product>}
|
|
36
|
+
*/
|
|
37
|
+
static async audit(artifacts, context) {
|
|
38
|
+
return adaptInsightToAuditProduct(artifacts, context, 'LCPDiscovery', (insight) => {
|
|
39
|
+
if (!insight.checklist) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return Audit.makeChecklistDetails(insight.checklist);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default LCPDiscoveryInsight;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default LCPPhasesInsight;
|
|
2
|
+
declare class LCPPhasesInsight extends Audit {
|
|
3
|
+
/**
|
|
4
|
+
* @param {Required<import('@paulirish/trace_engine/models/trace/insights/LCPPhases.js').LCPPhasesInsightModel>['phases']} phases
|
|
5
|
+
* @return {LH.Audit.Details.Table}
|
|
6
|
+
*/
|
|
7
|
+
static makePhaseTable(phases: Required<import("@paulirish/trace_engine/models/trace/insights/LCPPhases.js").LCPPhasesInsightModel>["phases"]): LH.Audit.Details.Table;
|
|
8
|
+
/**
|
|
9
|
+
* @param {LH.Artifacts} artifacts
|
|
10
|
+
* @param {LH.Audit.Context} context
|
|
11
|
+
* @return {Promise<LH.Audit.Product>}
|
|
12
|
+
*/
|
|
13
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
14
|
+
}
|
|
15
|
+
import { Audit } from '../audit.js';
|
|
16
|
+
//# sourceMappingURL=lcp-phases-insight.d.ts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
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/LCPPhases.js';
|
|
8
|
+
|
|
9
|
+
import {Audit} from '../audit.js';
|
|
10
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
+
import {adaptInsightToAuditProduct, maybeMakeNodeElementTable} 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/LCPPhases.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
class LCPPhasesInsight extends Audit {
|
|
17
|
+
/**
|
|
18
|
+
* @return {LH.Audit.Meta}
|
|
19
|
+
*/
|
|
20
|
+
static get meta() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'lcp-phases-insight',
|
|
23
|
+
title: str_(UIStrings.title),
|
|
24
|
+
failureTitle: str_(UIStrings.title),
|
|
25
|
+
description: str_(UIStrings.description),
|
|
26
|
+
guidanceLevel: 3,
|
|
27
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
28
|
+
replacesAudits: ['largest-contentful-paint-element'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {Required<import('@paulirish/trace_engine/models/trace/insights/LCPPhases.js').LCPPhasesInsightModel>['phases']} phases
|
|
34
|
+
* @return {LH.Audit.Details.Table}
|
|
35
|
+
*/
|
|
36
|
+
static makePhaseTable(phases) {
|
|
37
|
+
const {ttfb, loadDelay, loadTime, renderDelay} = phases;
|
|
38
|
+
|
|
39
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
40
|
+
const headings = [
|
|
41
|
+
{key: 'label', valueType: 'text', label: str_(UIStrings.phase)},
|
|
42
|
+
{key: 'duration', valueType: 'ms', label: str_(i18n.UIStrings.columnDuration)},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
46
|
+
let items = [
|
|
47
|
+
/* eslint-disable max-len */
|
|
48
|
+
{phase: 'timeToFirstByte', label: str_(UIStrings.timeToFirstByte), duration: ttfb},
|
|
49
|
+
{phase: 'resourceLoadDelay', label: str_(UIStrings.resourceLoadDelay), duration: loadDelay},
|
|
50
|
+
{phase: 'resourceLoadDuration', label: str_(UIStrings.resourceLoadDuration), duration: loadTime},
|
|
51
|
+
{phase: 'elementRenderDelay', label: str_(UIStrings.elementRenderDelay), duration: renderDelay},
|
|
52
|
+
/* eslint-enable max-len */
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
if (loadDelay === undefined) {
|
|
56
|
+
items = items.filter(item => item.phase !== 'resourceLoadDelay');
|
|
57
|
+
}
|
|
58
|
+
if (loadTime === undefined) {
|
|
59
|
+
items = items.filter(item => item.phase !== 'resourceLoadDuration');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return Audit.makeTableDetails(headings, items);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {LH.Artifacts} artifacts
|
|
67
|
+
* @param {LH.Audit.Context} context
|
|
68
|
+
* @return {Promise<LH.Audit.Product>}
|
|
69
|
+
*/
|
|
70
|
+
static async audit(artifacts, context) {
|
|
71
|
+
return adaptInsightToAuditProduct(artifacts, context, 'LCPPhases', (insight) => {
|
|
72
|
+
if (!insight.phases) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return Audit.makeListDetails([
|
|
77
|
+
maybeMakeNodeElementTable(
|
|
78
|
+
artifacts.TraceElements,
|
|
79
|
+
insight.lcpEvent?.args.data?.nodeId,
|
|
80
|
+
str_(i18n.UIStrings.columnElement)),
|
|
81
|
+
LCPPhasesInsight.makePhaseTable(insight.phases),
|
|
82
|
+
].filter(table => table !== undefined));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
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,53 @@
|
|
|
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
|
+
replacesAudits: ['critical-request-chains'],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {LH.Artifacts} artifacts
|
|
36
|
+
* @param {LH.Audit.Context} context
|
|
37
|
+
* @return {Promise<LH.Audit.Product>}
|
|
38
|
+
*/
|
|
39
|
+
static async audit(artifacts, context) {
|
|
40
|
+
// TODO: implement.
|
|
41
|
+
return adaptInsightToAuditProduct(artifacts, context, 'LongCriticalNetworkTree', (insight) => {
|
|
42
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
43
|
+
const headings = [
|
|
44
|
+
];
|
|
45
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
46
|
+
const items = [
|
|
47
|
+
];
|
|
48
|
+
return Audit.makeTableDetails(headings, items);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
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,57 @@
|
|
|
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
|
+
replacesAudits: ['render-blocking-resources'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {LH.Artifacts} artifacts
|
|
34
|
+
* @param {LH.Audit.Context} context
|
|
35
|
+
* @return {Promise<LH.Audit.Product>}
|
|
36
|
+
*/
|
|
37
|
+
static async audit(artifacts, context) {
|
|
38
|
+
// TODO: show UIStrings.noRenderBlocking if nothing was blocking?
|
|
39
|
+
return adaptInsightToAuditProduct(artifacts, context, 'RenderBlocking', (insight) => {
|
|
40
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
41
|
+
const headings = [
|
|
42
|
+
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
43
|
+
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnTransferSize)},
|
|
44
|
+
{key: 'wastedMs', valueType: 'timespanMs', label: str_(i18n.UIStrings.columnWastedMs)},
|
|
45
|
+
];
|
|
46
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
47
|
+
const items = insight.renderBlockingRequests.map(request => ({
|
|
48
|
+
url: request.args.data.url,
|
|
49
|
+
totalBytes: request.args.data.encodedDataLength,
|
|
50
|
+
wastedMs: insight.requestIdToWastedMs?.get(request.args.data.requestId),
|
|
51
|
+
}));
|
|
52
|
+
return Audit.makeTableDetails(headings, items);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
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,28 @@
|
|
|
1
|
+
export default ThirdPartiesInsight;
|
|
2
|
+
export type URLSummary = {
|
|
3
|
+
transferSize: number;
|
|
4
|
+
mainThreadTime: number;
|
|
5
|
+
url: string | LH.IcuMessage;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @typedef URLSummary
|
|
9
|
+
* @property {number} transferSize
|
|
10
|
+
* @property {number} mainThreadTime
|
|
11
|
+
* @property {string | LH.IcuMessage} url
|
|
12
|
+
*/
|
|
13
|
+
declare class ThirdPartiesInsight extends Audit {
|
|
14
|
+
/**
|
|
15
|
+
* @param {LH.Artifacts.Entity} entity
|
|
16
|
+
* @param {import('@paulirish/trace_engine/models/trace/insights/ThirdParties.js').ThirdPartiesInsightModel} insight
|
|
17
|
+
* @return {Array<URLSummary>}
|
|
18
|
+
*/
|
|
19
|
+
static makeSubItems(entity: LH.Artifacts.Entity, insight: import("@paulirish/trace_engine/models/trace/insights/ThirdParties.js").ThirdPartiesInsightModel): Array<URLSummary>;
|
|
20
|
+
/**
|
|
21
|
+
* @param {LH.Artifacts} artifacts
|
|
22
|
+
* @param {LH.Audit.Context} context
|
|
23
|
+
* @return {Promise<LH.Audit.Product>}
|
|
24
|
+
*/
|
|
25
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
26
|
+
}
|
|
27
|
+
import { Audit } from '../audit.js';
|
|
28
|
+
//# sourceMappingURL=third-parties-insight.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
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/ThirdParties.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/ThirdParties.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef URLSummary
|
|
18
|
+
* @property {number} transferSize
|
|
19
|
+
* @property {number} mainThreadTime
|
|
20
|
+
* @property {string | LH.IcuMessage} url
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
class ThirdPartiesInsight extends Audit {
|
|
24
|
+
/**
|
|
25
|
+
* @return {LH.Audit.Meta}
|
|
26
|
+
*/
|
|
27
|
+
static get meta() {
|
|
28
|
+
return {
|
|
29
|
+
id: 'third-parties-insight',
|
|
30
|
+
title: str_(UIStrings.title),
|
|
31
|
+
failureTitle: str_(UIStrings.title),
|
|
32
|
+
description: str_(UIStrings.description),
|
|
33
|
+
guidanceLevel: 3,
|
|
34
|
+
requiredArtifacts: ['traces', 'TraceElements'],
|
|
35
|
+
replacesAudits: ['third-party-summary'],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {LH.Artifacts.Entity} entity
|
|
41
|
+
* @param {import('@paulirish/trace_engine/models/trace/insights/ThirdParties.js').ThirdPartiesInsightModel} insight
|
|
42
|
+
* @return {Array<URLSummary>}
|
|
43
|
+
*/
|
|
44
|
+
static makeSubItems(entity, insight) {
|
|
45
|
+
const urls = [...insight.urlsByEntity.get(entity) ?? []];
|
|
46
|
+
return urls
|
|
47
|
+
.map(url => ({
|
|
48
|
+
url,
|
|
49
|
+
mainThreadTime: 0,
|
|
50
|
+
transferSize: 0,
|
|
51
|
+
...insight.summaryByUrl.get(url),
|
|
52
|
+
}))
|
|
53
|
+
// Sort by main thread time first, then transfer size to break ties.
|
|
54
|
+
.sort((a, b) => (b.mainThreadTime - a.mainThreadTime) || (b.transferSize - a.transferSize));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {LH.Artifacts} artifacts
|
|
59
|
+
* @param {LH.Audit.Context} context
|
|
60
|
+
* @return {Promise<LH.Audit.Product>}
|
|
61
|
+
*/
|
|
62
|
+
static async audit(artifacts, context) {
|
|
63
|
+
return adaptInsightToAuditProduct(artifacts, context, 'ThirdParties', (insight) => {
|
|
64
|
+
const thirdPartyEntities = [...insight.summaryByEntity.entries()]
|
|
65
|
+
.filter((([entity, _]) => entity !== insight.firstPartyEntity));
|
|
66
|
+
|
|
67
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
68
|
+
const headings = [
|
|
69
|
+
/* eslint-disable max-len */
|
|
70
|
+
{key: 'entity', valueType: 'text', label: str_(UIStrings.columnThirdParty), subItemsHeading: {key: 'url', valueType: 'url'}},
|
|
71
|
+
{key: 'transferSize', granularity: 1, valueType: 'bytes', label: str_(UIStrings.columnTransferSize), subItemsHeading: {key: 'transferSize'}},
|
|
72
|
+
{key: 'mainThreadTime', granularity: 1, valueType: 'ms', label: str_(UIStrings.columnMainThreadTime), subItemsHeading: {key: 'mainThreadTime'}},
|
|
73
|
+
/* eslint-enable max-len */
|
|
74
|
+
];
|
|
75
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
76
|
+
const items = thirdPartyEntities.map(([entity, summary]) => ({
|
|
77
|
+
entity: entity.name,
|
|
78
|
+
transferSize: summary.transferSize,
|
|
79
|
+
mainThreadTime: summary.mainThreadTime,
|
|
80
|
+
subItems: {
|
|
81
|
+
type: /** @type {const} */ ('subitems'),
|
|
82
|
+
items: ThirdPartiesInsight.makeSubItems(entity, insight),
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
return Audit.makeTableDetails(headings, items, {isEntityGrouped: true});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
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,54 @@
|
|
|
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
|
+
replacesAudits: ['viewport'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {LH.Artifacts} artifacts
|
|
34
|
+
* @param {LH.Audit.Context} context
|
|
35
|
+
* @return {Promise<LH.Audit.Product>}
|
|
36
|
+
*/
|
|
37
|
+
static async audit(artifacts, context) {
|
|
38
|
+
return adaptInsightToAuditProduct(artifacts, context, 'Viewport', (insight) => {
|
|
39
|
+
const nodeId = insight.viewportEvent?.args.data.node_id;
|
|
40
|
+
|
|
41
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
42
|
+
const headings = [
|
|
43
|
+
{key: 'node', valueType: 'node', label: ''},
|
|
44
|
+
];
|
|
45
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
46
|
+
const items = [
|
|
47
|
+
{node: makeNodeItemForNodeId(artifacts.TraceElements, nodeId)},
|
|
48
|
+
];
|
|
49
|
+
return Audit.makeTableDetails(headings, items);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default ViewportInsight;
|
|
@@ -26,7 +26,6 @@ export namespace UIStrings {
|
|
|
26
26
|
let rootCauseUnsizedMedia: string;
|
|
27
27
|
let rootCauseFontChanges: string;
|
|
28
28
|
let rootCauseInjectedIframe: string;
|
|
29
|
-
let rootCauseRenderBlockingRequest: string;
|
|
30
29
|
let displayValueShiftsFound: string;
|
|
31
30
|
}
|
|
32
31
|
import { Audit } from './audit.js';
|