lighthouse 11.7.0-dev.20240408 → 11.7.1

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.
Files changed (141) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/cli/test/smokehouse/core-tests.js +2 -0
  3. package/core/audits/accessibility/duplicate-id-active.d.ts +10 -0
  4. package/core/audits/accessibility/duplicate-id-active.js +42 -0
  5. package/core/audits/accessibility/target-size.js +1 -0
  6. package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +16 -0
  7. package/core/audits/byte-efficiency/byte-efficiency-audit.js +38 -1
  8. package/core/audits/byte-efficiency/offscreen-images.d.ts +11 -0
  9. package/core/audits/byte-efficiency/offscreen-images.js +15 -0
  10. package/core/audits/dobetterweb/uses-http2.d.ts +13 -0
  11. package/core/audits/dobetterweb/uses-http2.js +34 -2
  12. package/core/audits/layout-shift-elements.d.ts +16 -0
  13. package/core/audits/layout-shift-elements.js +101 -0
  14. package/core/audits/no-unload-listeners.d.ts +16 -0
  15. package/core/audits/no-unload-listeners.js +86 -0
  16. package/core/audits/preload-fonts.d.ts +5 -1
  17. package/core/audits/preload-fonts.js +10 -1
  18. package/core/audits/script-elements-test-audit.d.ts +14 -0
  19. package/core/audits/script-elements-test-audit.js +29 -0
  20. package/core/audits/seo/is-crawlable.d.ts +1 -2
  21. package/core/audits/seo/plugins.d.ts +15 -0
  22. package/core/audits/seo/plugins.js +150 -0
  23. package/core/audits/seo/tap-targets.d.ts +50 -0
  24. package/core/audits/seo/tap-targets.js +352 -0
  25. package/core/audits/uses-rel-preload.d.ts +5 -1
  26. package/core/audits/uses-rel-preload.js +11 -1
  27. package/core/audits/work-during-interaction.d.ts +2 -2
  28. package/core/audits/work-during-interaction.js +2 -2
  29. package/core/computed/js-bundles.d.ts +1 -1
  30. package/core/computed/metrics/lantern-first-contentful-paint.d.ts +82 -13
  31. package/core/computed/metrics/lantern-first-contentful-paint.js +178 -15
  32. package/core/computed/metrics/lantern-first-meaningful-paint.d.ts +12 -13
  33. package/core/computed/metrics/lantern-first-meaningful-paint.js +49 -10
  34. package/core/computed/metrics/lantern-interactive.d.ts +21 -13
  35. package/core/computed/metrics/lantern-interactive.js +84 -11
  36. package/core/computed/metrics/lantern-largest-contentful-paint.d.ts +25 -13
  37. package/core/computed/metrics/lantern-largest-contentful-paint.js +80 -12
  38. package/core/computed/metrics/lantern-max-potential-fid.d.ts +24 -13
  39. package/core/computed/metrics/lantern-max-potential-fid.js +64 -11
  40. package/core/computed/metrics/lantern-metric.d.ts +18 -9
  41. package/core/computed/metrics/lantern-metric.js +31 -13
  42. package/core/computed/metrics/lantern-speed-index.d.ts +32 -13
  43. package/core/computed/metrics/lantern-speed-index.js +116 -12
  44. package/core/computed/metrics/lantern-total-blocking-time.d.ts +25 -13
  45. package/core/computed/metrics/lantern-total-blocking-time.js +94 -10
  46. package/core/computed/metrics/metric.js +3 -1
  47. package/core/computed/module-duplication.d.ts +1 -1
  48. package/core/computed/page-dependency-graph.js +1 -2
  49. package/core/config/default-config.js +74 -46
  50. package/core/config/experimental-config.js +0 -11
  51. package/core/config/metrics-to-audits.d.ts +19 -0
  52. package/core/config/metrics-to-audits.js +62 -0
  53. package/core/gather/gatherers/accessibility.js +3 -1
  54. package/core/gather/gatherers/global-listeners.d.ts +27 -0
  55. package/core/gather/gatherers/global-listeners.js +108 -0
  56. package/core/gather/gatherers/script-elements.d.ts +21 -0
  57. package/core/gather/gatherers/script-elements.js +100 -0
  58. package/core/gather/gatherers/seo/embedded-content.d.ts +10 -0
  59. package/core/gather/gatherers/seo/embedded-content.js +63 -0
  60. package/core/gather/gatherers/seo/tap-targets.d.ts +21 -0
  61. package/core/gather/gatherers/seo/tap-targets.js +389 -0
  62. package/core/gather/gatherers/trace-elements.d.ts +10 -0
  63. package/core/gather/gatherers/trace-elements.js +19 -0
  64. package/core/lib/lantern/page-dependency-graph.d.ts +4 -4
  65. package/core/lib/lantern/page-dependency-graph.js +5 -5
  66. package/core/lib/lighthouse-compatibility.js +10 -53
  67. package/dist/report/bundle.esm.js +1 -1
  68. package/dist/report/flow.js +14 -14
  69. package/dist/report/standalone.js +1 -1
  70. package/flow-report/src/summary/category.tsx +12 -10
  71. package/package.json +1 -1
  72. package/report/renderer/performance-category-renderer.d.ts +7 -0
  73. package/report/renderer/performance-category-renderer.js +11 -1
  74. package/report/renderer/report-utils.js +10 -13
  75. package/shared/localization/locales/ar-XB.json +64 -1
  76. package/shared/localization/locales/ar.json +64 -1
  77. package/shared/localization/locales/bg.json +64 -1
  78. package/shared/localization/locales/ca.json +64 -1
  79. package/shared/localization/locales/cs.json +64 -1
  80. package/shared/localization/locales/da.json +64 -1
  81. package/shared/localization/locales/de.json +64 -1
  82. package/shared/localization/locales/el.json +64 -1
  83. package/shared/localization/locales/en-GB.json +64 -1
  84. package/shared/localization/locales/en-US.json +65 -2
  85. package/shared/localization/locales/en-XA.json +64 -1
  86. package/shared/localization/locales/en-XL.json +65 -2
  87. package/shared/localization/locales/es-419.json +64 -1
  88. package/shared/localization/locales/es.json +64 -1
  89. package/shared/localization/locales/fi.json +64 -1
  90. package/shared/localization/locales/fil.json +64 -1
  91. package/shared/localization/locales/fr.json +64 -1
  92. package/shared/localization/locales/he.json +64 -1
  93. package/shared/localization/locales/hi.json +64 -1
  94. package/shared/localization/locales/hr.json +64 -1
  95. package/shared/localization/locales/hu.json +64 -1
  96. package/shared/localization/locales/id.json +64 -1
  97. package/shared/localization/locales/it.json +64 -1
  98. package/shared/localization/locales/ja.json +64 -1
  99. package/shared/localization/locales/ko.json +64 -1
  100. package/shared/localization/locales/lt.json +64 -1
  101. package/shared/localization/locales/lv.json +64 -1
  102. package/shared/localization/locales/nl.json +64 -1
  103. package/shared/localization/locales/no.json +64 -1
  104. package/shared/localization/locales/pl.json +64 -1
  105. package/shared/localization/locales/pt-PT.json +64 -1
  106. package/shared/localization/locales/pt.json +64 -1
  107. package/shared/localization/locales/ro.json +64 -1
  108. package/shared/localization/locales/ru.json +64 -1
  109. package/shared/localization/locales/sk.json +64 -1
  110. package/shared/localization/locales/sl.json +64 -1
  111. package/shared/localization/locales/sr-Latn.json +64 -1
  112. package/shared/localization/locales/sr.json +64 -1
  113. package/shared/localization/locales/sv.json +64 -1
  114. package/shared/localization/locales/ta.json +64 -1
  115. package/shared/localization/locales/te.json +64 -1
  116. package/shared/localization/locales/th.json +64 -1
  117. package/shared/localization/locales/tr.json +64 -1
  118. package/shared/localization/locales/uk.json +64 -1
  119. package/shared/localization/locales/vi.json +64 -1
  120. package/shared/localization/locales/zh-HK.json +64 -1
  121. package/shared/localization/locales/zh-TW.json +64 -1
  122. package/shared/localization/locales/zh.json +64 -1
  123. package/tsconfig.json +0 -1
  124. package/types/artifacts.d.ts +17 -3
  125. package/types/config.d.ts +1 -0
  126. package/types/lhr/audit-details.d.ts +4 -9
  127. package/types/lhr/lhr.d.ts +2 -0
  128. package/core/lib/lantern/metrics/first-contentful-paint.d.ts +0 -79
  129. package/core/lib/lantern/metrics/first-contentful-paint.js +0 -200
  130. package/core/lib/lantern/metrics/first-meaningful-paint.d.ts +0 -6
  131. package/core/lib/lantern/metrics/first-meaningful-paint.js +0 -66
  132. package/core/lib/lantern/metrics/interactive.d.ts +0 -26
  133. package/core/lib/lantern/metrics/interactive.js +0 -112
  134. package/core/lib/lantern/metrics/largest-contentful-paint.d.ts +0 -19
  135. package/core/lib/lantern/metrics/largest-contentful-paint.js +0 -108
  136. package/core/lib/lantern/metrics/max-potential-fid.d.ts +0 -30
  137. package/core/lib/lantern/metrics/max-potential-fid.js +0 -92
  138. package/core/lib/lantern/metrics/speed-index.d.ts +0 -38
  139. package/core/lib/lantern/metrics/speed-index.js +0 -145
  140. package/core/lib/lantern/metrics/total-blocking-time.d.ts +0 -31
  141. package/core/lib/lantern/metrics/total-blocking-time.js +0 -128
@@ -1,38 +0,0 @@
1
- export type Node = import('../base-node.js').Node;
2
- /** @typedef {import('../base-node.js').Node} Node */
3
- export class SpeedIndex extends Metric {
4
- /**
5
- * @param {Node} dependencyGraph
6
- * @return {Node}
7
- */
8
- static getOptimisticGraph(dependencyGraph: Node): Node;
9
- /**
10
- * @param {Node} dependencyGraph
11
- * @return {Node}
12
- */
13
- static getPessimisticGraph(dependencyGraph: Node): Node;
14
- /**
15
- * @param {LH.Gatherer.Simulation.Result} simulationResult
16
- * @param {import('../metric.js').Extras} extras
17
- * @return {LH.Gatherer.Simulation.Result}
18
- */
19
- static getEstimateFromSimulation(simulationResult: LH.Gatherer.Simulation.Result, extras: import('../metric.js').Extras): LH.Gatherer.Simulation.Result;
20
- /**
21
- * Approximate speed index using layout events from the simulated node timings.
22
- * The layout-based speed index is the weighted average of the endTime of CPU nodes that contained
23
- * a 'Layout' task. log(duration) is used as the weight to stand for "significance" to the page.
24
- *
25
- * If no layout events can be found or the endTime of a CPU task is too early, FCP is used instead.
26
- *
27
- * This approach was determined after evaluating the accuracy/complexity tradeoff of many
28
- * different methods. Read more in the evaluation doc.
29
- *
30
- * @see https://docs.google.com/document/d/1qJWXwxoyVLVadezIp_Tgdk867G3tDNkkVRvUJSH3K1E/edit#
31
- * @param {LH.Gatherer.Simulation.Result['nodeTimings']} nodeTimings
32
- * @param {number} fcpTimeInMs
33
- * @return {number}
34
- */
35
- static computeLayoutBasedSpeedIndex(nodeTimings: LH.Gatherer.Simulation.Result['nodeTimings'], fcpTimeInMs: number): number;
36
- }
37
- import { Metric } from '../metric.js';
38
- //# sourceMappingURL=speed-index.d.ts.map
@@ -1,145 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2024 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import * as Lantern from '../types/lantern.js';
8
- import {Metric} from '../metric.js';
9
- import {BaseNode} from '../base-node.js';
10
- // TODO(15841): move this default config value into lib/lantern
11
- import {throttling as defaultThrottling} from '../../../config/constants.js';
12
-
13
- /** @typedef {import('../base-node.js').Node} Node */
14
-
15
- class SpeedIndex extends Metric {
16
- /**
17
- * @return {LH.Gatherer.Simulation.MetricCoefficients}
18
- */
19
- static get COEFFICIENTS() {
20
- return {
21
- // Negative intercept is OK because estimate is Math.max(FCP, Speed Index) and
22
- // the optimistic estimate is based on the real observed speed index rather than a real
23
- // lantern graph.
24
- intercept: -250,
25
- optimistic: 1.4,
26
- pessimistic: 0.65,
27
- };
28
- }
29
-
30
- /**
31
- * @param {number} rttMs
32
- * @return {LH.Gatherer.Simulation.MetricCoefficients}
33
- */
34
- static getScaledCoefficients(rttMs) { // eslint-disable-line no-unused-vars
35
- // We want to scale our default coefficients based on the speed of the connection.
36
- // We will linearly interpolate coefficients for the passed-in rttMs based on two pre-determined points:
37
- // 1. Baseline point of 30 ms RTT where Speed Index should be a ~50/50 blend of optimistic/pessimistic.
38
- // 30 ms was based on a typical home WiFi connection's actual RTT.
39
- // Coefficients here follow from the fact that the optimistic estimate should be very close
40
- // to reality at this connection speed and the pessimistic estimate compensates for minor
41
- // connection speed differences.
42
- // 2. Default throttled point of 150 ms RTT where the default coefficients have been determined to be most accurate.
43
- // Coefficients here were determined through thorough analysis and linear regression on the
44
- // lantern test data set. See core/scripts/test-lantern.sh for more detail.
45
- // While the coefficients haven't been analyzed at the interpolated points, it's our current best effort.
46
- const defaultCoefficients = this.COEFFICIENTS;
47
- const defaultRttExcess = defaultThrottling.mobileSlow4G.rttMs - 30;
48
- const multiplier = Math.max((rttMs - 30) / defaultRttExcess, 0);
49
-
50
- return {
51
- intercept: defaultCoefficients.intercept * multiplier,
52
- optimistic: 0.5 + (defaultCoefficients.optimistic - 0.5) * multiplier,
53
- pessimistic: 0.5 + (defaultCoefficients.pessimistic - 0.5) * multiplier,
54
- };
55
- }
56
-
57
- /**
58
- * @param {Node} dependencyGraph
59
- * @return {Node}
60
- */
61
- static getOptimisticGraph(dependencyGraph) {
62
- return dependencyGraph;
63
- }
64
-
65
- /**
66
- * @param {Node} dependencyGraph
67
- * @return {Node}
68
- */
69
- static getPessimisticGraph(dependencyGraph) {
70
- return dependencyGraph;
71
- }
72
-
73
- /**
74
- * @param {LH.Gatherer.Simulation.Result} simulationResult
75
- * @param {import('../metric.js').Extras} extras
76
- * @return {LH.Gatherer.Simulation.Result}
77
- */
78
- static getEstimateFromSimulation(simulationResult, extras) {
79
- if (!extras.fcpResult) throw new Error('missing fcpResult');
80
- if (!extras.speedline) throw new Error('missing speedline');
81
-
82
- const fcpTimeInMs = extras.fcpResult.pessimisticEstimate.timeInMs;
83
- const estimate = extras.optimistic
84
- ? extras.speedline.speedIndex
85
- : SpeedIndex.computeLayoutBasedSpeedIndex(simulationResult.nodeTimings, fcpTimeInMs);
86
- return {
87
- timeInMs: estimate,
88
- nodeTimings: simulationResult.nodeTimings,
89
- };
90
- }
91
-
92
- /**
93
- * @param {Lantern.Simulation.MetricComputationDataInput} data
94
- * @param {Omit<import('../metric.js').Extras, 'optimistic'>=} extras
95
- * @return {Promise<LH.Artifacts.LanternMetric>}
96
- */
97
- static async compute(data, extras) {
98
- const fcpResult = extras?.fcpResult;
99
- if (!fcpResult) {
100
- throw new Error('FCP is required to calculate the SpeedIndex metric');
101
- }
102
-
103
- const metricResult = await super.compute(data, extras);
104
- metricResult.timing = Math.max(metricResult.timing, fcpResult.timing);
105
- return metricResult;
106
- }
107
-
108
- /**
109
- * Approximate speed index using layout events from the simulated node timings.
110
- * The layout-based speed index is the weighted average of the endTime of CPU nodes that contained
111
- * a 'Layout' task. log(duration) is used as the weight to stand for "significance" to the page.
112
- *
113
- * If no layout events can be found or the endTime of a CPU task is too early, FCP is used instead.
114
- *
115
- * This approach was determined after evaluating the accuracy/complexity tradeoff of many
116
- * different methods. Read more in the evaluation doc.
117
- *
118
- * @see https://docs.google.com/document/d/1qJWXwxoyVLVadezIp_Tgdk867G3tDNkkVRvUJSH3K1E/edit#
119
- * @param {LH.Gatherer.Simulation.Result['nodeTimings']} nodeTimings
120
- * @param {number} fcpTimeInMs
121
- * @return {number}
122
- */
123
- static computeLayoutBasedSpeedIndex(nodeTimings, fcpTimeInMs) {
124
- /** @type {Array<{time: number, weight: number}>} */
125
- const layoutWeights = [];
126
- for (const [node, timing] of nodeTimings.entries()) {
127
- if (node.type !== BaseNode.TYPES.CPU) continue;
128
-
129
- if (node.childEvents.some(x => x.name === 'Layout')) {
130
- const timingWeight = Math.max(Math.log2(timing.endTime - timing.startTime), 0);
131
- layoutWeights.push({time: timing.endTime, weight: timingWeight});
132
- }
133
- }
134
-
135
- const totalWeightedTime = layoutWeights
136
- .map(evt => evt.weight * Math.max(evt.time, fcpTimeInMs))
137
- .reduce((a, b) => a + b, 0);
138
- const totalWeight = layoutWeights.map(evt => evt.weight).reduce((a, b) => a + b, 0);
139
-
140
- if (!totalWeight) return fcpTimeInMs;
141
- return totalWeightedTime / totalWeight;
142
- }
143
- }
144
-
145
- export {SpeedIndex};
@@ -1,31 +0,0 @@
1
- export type Node = import('../base-node.js').Node;
2
- /** @typedef {import('../base-node.js').Node} Node */
3
- export class TotalBlockingTime extends Metric {
4
- /**
5
- * @param {Node} dependencyGraph
6
- * @return {Node}
7
- */
8
- static getOptimisticGraph(dependencyGraph: Node): Node;
9
- /**
10
- * @param {Node} dependencyGraph
11
- * @return {Node}
12
- */
13
- static getPessimisticGraph(dependencyGraph: Node): Node;
14
- /**
15
- * @param {LH.Gatherer.Simulation.Result} simulation
16
- * @param {import('../metric.js').Extras} extras
17
- * @return {LH.Gatherer.Simulation.Result}
18
- */
19
- static getEstimateFromSimulation(simulation: LH.Gatherer.Simulation.Result, extras: import('../metric.js').Extras): LH.Gatherer.Simulation.Result;
20
- /**
21
- * @param {LH.Gatherer.Simulation.Result['nodeTimings']} nodeTimings
22
- * @param {number} minDurationMs
23
- */
24
- static getTopLevelEvents(nodeTimings: LH.Gatherer.Simulation.Result['nodeTimings'], minDurationMs: number): {
25
- start: number;
26
- end: number;
27
- duration: number;
28
- }[];
29
- }
30
- import { Metric } from '../metric.js';
31
- //# sourceMappingURL=total-blocking-time.d.ts.map
@@ -1,128 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2024 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import * as Lantern from '../types/lantern.js';
8
- import {Metric} from '../metric.js';
9
- import {BaseNode} from '../base-node.js';
10
- import {BLOCKING_TIME_THRESHOLD, calculateSumOfBlockingTime} from '../../../computed/metrics/tbt-utils.js';
11
-
12
- /** @typedef {import('../base-node.js').Node} Node */
13
-
14
- class TotalBlockingTime extends Metric {
15
- /**
16
- * @return {LH.Gatherer.Simulation.MetricCoefficients}
17
- */
18
- static get COEFFICIENTS() {
19
- return {
20
- intercept: 0,
21
- optimistic: 0.5,
22
- pessimistic: 0.5,
23
- };
24
- }
25
-
26
- /**
27
- * @param {Node} dependencyGraph
28
- * @return {Node}
29
- */
30
- static getOptimisticGraph(dependencyGraph) {
31
- return dependencyGraph;
32
- }
33
-
34
- /**
35
- * @param {Node} dependencyGraph
36
- * @return {Node}
37
- */
38
- static getPessimisticGraph(dependencyGraph) {
39
- return dependencyGraph;
40
- }
41
-
42
- /**
43
- * @param {LH.Gatherer.Simulation.Result} simulation
44
- * @param {import('../metric.js').Extras} extras
45
- * @return {LH.Gatherer.Simulation.Result}
46
- */
47
- static getEstimateFromSimulation(simulation, extras) {
48
- if (!extras.fcpResult) throw new Error('missing fcpResult');
49
- if (!extras.interactiveResult) throw new Error('missing interactiveResult');
50
-
51
- // Intentionally use the opposite FCP estimate. A pessimistic FCP is higher than equal to an
52
- // optimistic FCP, which means potentially more tasks are excluded from the Total Blocking Time
53
- // computation. So a more pessimistic FCP gives a more optimistic Total Blocking Time for the
54
- // same work.
55
- const fcpTimeInMs = extras.optimistic
56
- ? extras.fcpResult.pessimisticEstimate.timeInMs
57
- : extras.fcpResult.optimisticEstimate.timeInMs;
58
-
59
- // Similarly, we always have pessimistic TTI >= optimistic TTI. Therefore, picking optimistic
60
- // TTI means our window of interest is smaller and thus potentially more tasks are excluded from
61
- // Total Blocking Time computation, yielding a lower (more optimistic) Total Blocking Time value
62
- // for the same work.
63
- const interactiveTimeMs = extras.optimistic
64
- ? extras.interactiveResult.optimisticEstimate.timeInMs
65
- : extras.interactiveResult.pessimisticEstimate.timeInMs;
66
-
67
- const minDurationMs = BLOCKING_TIME_THRESHOLD;
68
-
69
- const events = TotalBlockingTime.getTopLevelEvents(
70
- simulation.nodeTimings,
71
- minDurationMs
72
- );
73
-
74
- return {
75
- timeInMs: calculateSumOfBlockingTime(
76
- events,
77
- fcpTimeInMs,
78
- interactiveTimeMs
79
- ),
80
- nodeTimings: simulation.nodeTimings,
81
- };
82
- }
83
-
84
- /**
85
- * @param {Lantern.Simulation.MetricComputationDataInput} data
86
- * @param {Omit<import('../metric.js').Extras, 'optimistic'>=} extras
87
- * @return {Promise<LH.Artifacts.LanternMetric>}
88
- */
89
- static async compute(data, extras) {
90
- const fcpResult = extras?.fcpResult;
91
- if (!fcpResult) {
92
- throw new Error('FCP is required to calculate the TBT metric');
93
- }
94
-
95
- const interactiveResult = extras?.fcpResult;
96
- if (!interactiveResult) {
97
- throw new Error('Interactive is required to calculate the TBT metric');
98
- }
99
-
100
- return super.compute(data, extras);
101
- }
102
-
103
- /**
104
- * @param {LH.Gatherer.Simulation.Result['nodeTimings']} nodeTimings
105
- * @param {number} minDurationMs
106
- */
107
- static getTopLevelEvents(nodeTimings, minDurationMs) {
108
- /** @type {Array<{start: number, end: number, duration: number}>}
109
- */
110
- const events = [];
111
-
112
- for (const [node, timing] of nodeTimings.entries()) {
113
- if (node.type !== BaseNode.TYPES.CPU) continue;
114
- // Filtering out events below minimum duration.
115
- if (timing.duration < minDurationMs) continue;
116
-
117
- events.push({
118
- start: timing.startTime,
119
- end: timing.endTime,
120
- duration: timing.duration,
121
- });
122
- }
123
-
124
- return events;
125
- }
126
- }
127
-
128
- export {TotalBlockingTime};