lighthouse 11.7.1 → 12.0.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.
Files changed (272) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/cli/bin.js +0 -7
  3. package/cli/cli-flags.d.ts +1 -5
  4. package/cli/cli-flags.js +4 -8
  5. package/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +14 -14
  6. package/cli/test/smokehouse/config/exclusions.js +3 -0
  7. package/cli/test/smokehouse/core-tests.js +6 -20
  8. package/cli/test/smokehouse/frontends/smokehouse-bin.js +2 -2
  9. package/core/audits/accessibility/aria-conditional-attr.d.ts +10 -0
  10. package/core/audits/accessibility/aria-conditional-attr.js +43 -0
  11. package/core/audits/accessibility/{duplicate-id-active.d.ts → aria-deprecated-role.d.ts} +3 -3
  12. package/core/audits/accessibility/aria-deprecated-role.js +43 -0
  13. package/core/audits/accessibility/aria-prohibited-attr.d.ts +10 -0
  14. package/core/audits/accessibility/aria-prohibited-attr.js +44 -0
  15. package/core/audits/accessibility/target-size.js +0 -1
  16. package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +0 -16
  17. package/core/audits/byte-efficiency/byte-efficiency-audit.js +1 -38
  18. package/core/audits/byte-efficiency/offscreen-images.d.ts +0 -11
  19. package/core/audits/byte-efficiency/offscreen-images.js +0 -15
  20. package/core/audits/byte-efficiency/render-blocking-resources.js +27 -26
  21. package/core/audits/byte-efficiency/unminified-css.js +2 -2
  22. package/core/audits/byte-efficiency/unused-css-rules.js +3 -1
  23. package/core/audits/dobetterweb/uses-http2.d.ts +0 -13
  24. package/core/audits/dobetterweb/uses-http2.js +4 -38
  25. package/core/audits/font-display.js +2 -2
  26. package/core/audits/layout-shifts.js +1 -1
  27. package/core/audits/preload-fonts.d.ts +1 -5
  28. package/core/audits/preload-fonts.js +1 -10
  29. package/core/audits/prioritize-lcp-image.js +2 -2
  30. package/core/audits/redirects-http.d.ts +19 -0
  31. package/core/audits/redirects-http.js +75 -0
  32. package/core/audits/resource-summary.d.ts +2 -0
  33. package/core/audits/resource-summary.js +5 -4
  34. package/core/audits/seo/is-crawlable.d.ts +2 -1
  35. package/core/audits/seo/link-text.js +12 -0
  36. package/core/audits/uses-rel-preload.d.ts +1 -5
  37. package/core/audits/uses-rel-preload.js +5 -15
  38. package/core/audits/work-during-interaction.d.ts +2 -2
  39. package/core/audits/work-during-interaction.js +2 -2
  40. package/core/computed/js-bundles.d.ts +1 -1
  41. package/core/computed/metrics/lantern-first-contentful-paint.d.ts +13 -82
  42. package/core/computed/metrics/lantern-first-contentful-paint.js +16 -178
  43. package/core/computed/metrics/lantern-first-meaningful-paint.d.ts +13 -12
  44. package/core/computed/metrics/lantern-first-meaningful-paint.js +11 -49
  45. package/core/computed/metrics/lantern-interactive.d.ts +13 -21
  46. package/core/computed/metrics/lantern-interactive.js +12 -84
  47. package/core/computed/metrics/lantern-largest-contentful-paint.d.ts +13 -25
  48. package/core/computed/metrics/lantern-largest-contentful-paint.js +13 -80
  49. package/core/computed/metrics/lantern-max-potential-fid.d.ts +13 -24
  50. package/core/computed/metrics/lantern-max-potential-fid.js +12 -64
  51. package/core/computed/metrics/lantern-metric.d.ts +14 -18
  52. package/core/computed/metrics/lantern-metric.js +34 -30
  53. package/core/computed/metrics/lantern-speed-index.d.ts +13 -32
  54. package/core/computed/metrics/lantern-speed-index.js +13 -116
  55. package/core/computed/metrics/lantern-total-blocking-time.d.ts +13 -25
  56. package/core/computed/metrics/lantern-total-blocking-time.js +10 -94
  57. package/core/computed/metrics/metric.js +1 -3
  58. package/core/computed/module-duplication.d.ts +1 -1
  59. package/core/computed/navigation-insights.d.ts +36 -0
  60. package/core/computed/navigation-insights.js +35 -0
  61. package/core/computed/page-dependency-graph.js +3 -7
  62. package/core/computed/resource-summary.d.ts +10 -12
  63. package/core/computed/resource-summary.js +12 -19
  64. package/core/computed/trace-engine-result.d.ts +16 -3
  65. package/core/computed/trace-engine-result.js +19 -14
  66. package/core/computed/unused-css.d.ts +3 -1
  67. package/core/computed/unused-css.js +6 -5
  68. package/core/config/config-helpers.js +0 -4
  69. package/core/config/constants.js +0 -1
  70. package/core/config/default-config.js +63 -142
  71. package/core/config/experimental-config.js +11 -0
  72. package/core/config/filters.js +0 -1
  73. package/core/gather/driver/navigation.js +4 -1
  74. package/core/gather/driver/prepare.js +1 -1
  75. package/core/gather/driver/target-manager.js +4 -3
  76. package/core/gather/driver/wait-for-condition.js +2 -3
  77. package/core/gather/driver.d.ts +12 -0
  78. package/core/gather/driver.js +27 -0
  79. package/core/gather/gatherers/accessibility.js +4 -6
  80. package/core/gather/gatherers/css-usage.d.ts +0 -21
  81. package/core/gather/gatherers/css-usage.js +9 -119
  82. package/core/gather/gatherers/root-causes.d.ts +2 -2
  83. package/core/gather/gatherers/root-causes.js +6 -5
  84. package/core/gather/gatherers/stylesheets.d.ts +26 -0
  85. package/core/gather/gatherers/stylesheets.js +138 -0
  86. package/core/gather/gatherers/trace-elements.d.ts +2 -12
  87. package/core/gather/gatherers/trace-elements.js +2 -21
  88. package/core/gather/navigation-runner.js +3 -1
  89. package/core/gather/session.d.ts +8 -0
  90. package/core/gather/session.js +14 -1
  91. package/core/lib/emulation.js +2 -2
  92. package/core/lib/i18n/i18n.d.ts +0 -1
  93. package/core/lib/i18n/i18n.js +0 -2
  94. package/core/lib/lantern/cpu-node.d.ts +7 -1
  95. package/core/lib/lantern/cpu-node.js +12 -2
  96. package/core/lib/lantern/lantern-error.d.ts +8 -0
  97. package/core/lib/lantern/lantern-error.js +9 -0
  98. package/core/lib/lantern/metric.js +2 -6
  99. package/core/lib/lantern/metrics/first-contentful-paint.d.ts +79 -0
  100. package/core/lib/lantern/metrics/first-contentful-paint.js +200 -0
  101. package/core/lib/lantern/metrics/first-meaningful-paint.d.ts +6 -0
  102. package/core/lib/lantern/metrics/first-meaningful-paint.js +64 -0
  103. package/core/lib/lantern/metrics/interactive.d.ts +26 -0
  104. package/core/lib/lantern/metrics/interactive.js +112 -0
  105. package/core/lib/lantern/metrics/largest-contentful-paint.d.ts +19 -0
  106. package/core/lib/lantern/metrics/largest-contentful-paint.js +108 -0
  107. package/core/lib/lantern/metrics/max-potential-fid.d.ts +30 -0
  108. package/core/lib/lantern/metrics/max-potential-fid.js +92 -0
  109. package/core/lib/lantern/metrics/speed-index.d.ts +38 -0
  110. package/core/lib/lantern/metrics/speed-index.js +144 -0
  111. package/core/lib/lantern/metrics/total-blocking-time.d.ts +31 -0
  112. package/core/lib/lantern/metrics/total-blocking-time.js +128 -0
  113. package/core/lib/lantern/network-node.js +28 -4
  114. package/core/lib/lantern/page-dependency-graph.d.ts +4 -4
  115. package/core/lib/lantern/page-dependency-graph.js +19 -7
  116. package/core/lib/lantern/simulator/connection-pool.d.ts +2 -12
  117. package/core/lib/lantern/simulator/connection-pool.js +3 -22
  118. package/core/lib/lantern/simulator/network-analyzer.js +1 -12
  119. package/core/lib/lantern/simulator/simulator.d.ts +2 -4
  120. package/core/lib/lantern/simulator/simulator.js +7 -14
  121. package/core/lib/lantern/types/lantern.d.ts +5 -3
  122. package/core/lib/lantern-trace-saver.js +0 -1
  123. package/core/lib/lh-error.d.ts +9 -0
  124. package/core/lib/lh-error.js +13 -3
  125. package/core/lib/lighthouse-compatibility.js +53 -10
  126. package/core/lib/navigation-error.js +3 -0
  127. package/core/lib/network-request.d.ts +1 -0
  128. package/core/lib/network-request.js +28 -0
  129. package/core/runner.js +18 -25
  130. package/dist/report/bundle.esm.js +11 -112
  131. package/dist/report/flow.js +16 -117
  132. package/dist/report/standalone.js +12 -113
  133. package/flow-report/src/help-dialog.tsx +0 -1
  134. package/flow-report/src/i18n/i18n.d.ts +0 -4
  135. package/flow-report/src/i18n/ui-strings.d.ts +0 -1
  136. package/flow-report/src/i18n/ui-strings.js +0 -2
  137. package/flow-report/src/summary/category.tsx +10 -12
  138. package/package.json +5 -5
  139. package/readme.md +4 -4
  140. package/report/assets/styles.css +1 -60
  141. package/report/assets/templates.html +0 -95
  142. package/report/renderer/category-renderer.js +1 -1
  143. package/report/renderer/components.d.ts +2 -2
  144. package/report/renderer/components.js +2 -103
  145. package/report/renderer/dom.d.ts +1 -1
  146. package/report/renderer/dom.js +1 -1
  147. package/report/renderer/performance-category-renderer.d.ts +0 -7
  148. package/report/renderer/performance-category-renderer.js +1 -32
  149. package/report/renderer/report-renderer.js +3 -13
  150. package/report/renderer/report-ui-features.js +1 -1
  151. package/report/renderer/report-utils.d.ts +0 -1
  152. package/report/renderer/report-utils.js +13 -13
  153. package/shared/localization/locales/ar-XB.json +62 -329
  154. package/shared/localization/locales/ar.json +62 -329
  155. package/shared/localization/locales/bg.json +62 -329
  156. package/shared/localization/locales/ca.json +62 -329
  157. package/shared/localization/locales/cs.json +62 -329
  158. package/shared/localization/locales/da.json +62 -329
  159. package/shared/localization/locales/de.json +62 -329
  160. package/shared/localization/locales/el.json +62 -329
  161. package/shared/localization/locales/en-GB.json +62 -329
  162. package/shared/localization/locales/en-US.json +41 -272
  163. package/shared/localization/locales/en-XA.json +62 -329
  164. package/shared/localization/locales/en-XL.json +41 -272
  165. package/shared/localization/locales/es-419.json +62 -329
  166. package/shared/localization/locales/es.json +62 -329
  167. package/shared/localization/locales/fi.json +62 -329
  168. package/shared/localization/locales/fil.json +61 -328
  169. package/shared/localization/locales/fr.json +62 -329
  170. package/shared/localization/locales/he.json +62 -329
  171. package/shared/localization/locales/hi.json +62 -329
  172. package/shared/localization/locales/hr.json +63 -330
  173. package/shared/localization/locales/hu.json +62 -329
  174. package/shared/localization/locales/id.json +62 -329
  175. package/shared/localization/locales/it.json +62 -329
  176. package/shared/localization/locales/ja.json +62 -329
  177. package/shared/localization/locales/ko.json +62 -329
  178. package/shared/localization/locales/lt.json +62 -329
  179. package/shared/localization/locales/lv.json +62 -329
  180. package/shared/localization/locales/nl.json +62 -329
  181. package/shared/localization/locales/no.json +62 -329
  182. package/shared/localization/locales/pl.json +61 -328
  183. package/shared/localization/locales/pt-PT.json +62 -329
  184. package/shared/localization/locales/pt.json +64 -331
  185. package/shared/localization/locales/ro.json +62 -329
  186. package/shared/localization/locales/ru.json +62 -329
  187. package/shared/localization/locales/sk.json +62 -329
  188. package/shared/localization/locales/sl.json +62 -329
  189. package/shared/localization/locales/sr-Latn.json +62 -329
  190. package/shared/localization/locales/sr.json +62 -329
  191. package/shared/localization/locales/sv.json +62 -329
  192. package/shared/localization/locales/ta.json +61 -328
  193. package/shared/localization/locales/te.json +62 -329
  194. package/shared/localization/locales/th.json +62 -329
  195. package/shared/localization/locales/tr.json +62 -329
  196. package/shared/localization/locales/uk.json +62 -329
  197. package/shared/localization/locales/vi.json +61 -328
  198. package/shared/localization/locales/zh-HK.json +62 -329
  199. package/shared/localization/locales/zh-TW.json +61 -328
  200. package/shared/localization/locales/zh.json +62 -329
  201. package/tsconfig.json +1 -3
  202. package/types/artifacts.d.ts +21 -110
  203. package/types/audit.d.ts +0 -10
  204. package/types/config.d.ts +0 -1
  205. package/types/externs.d.ts +0 -2
  206. package/types/gatherer.d.ts +3 -0
  207. package/types/internal/smokehouse.d.ts +1 -1
  208. package/types/lh.d.ts +0 -2
  209. package/types/lhr/audit-details.d.ts +9 -4
  210. package/types/lhr/lhr.d.ts +0 -4
  211. package/types/lhr/settings.d.ts +0 -4
  212. package/core/audits/accessibility/duplicate-id-active.js +0 -42
  213. package/core/audits/content-width.d.ts +0 -17
  214. package/core/audits/content-width.js +0 -76
  215. package/core/audits/installable-manifest.d.ts +0 -111
  216. package/core/audits/installable-manifest.js +0 -248
  217. package/core/audits/layout-shift-elements.d.ts +0 -16
  218. package/core/audits/layout-shift-elements.js +0 -101
  219. package/core/audits/manual/pwa-cross-browser.d.ts +0 -12
  220. package/core/audits/manual/pwa-cross-browser.js +0 -40
  221. package/core/audits/manual/pwa-each-page-has-url.d.ts +0 -12
  222. package/core/audits/manual/pwa-each-page-has-url.js +0 -38
  223. package/core/audits/manual/pwa-page-transitions.d.ts +0 -12
  224. package/core/audits/manual/pwa-page-transitions.js +0 -38
  225. package/core/audits/maskable-icon.d.ts +0 -25
  226. package/core/audits/maskable-icon.js +0 -70
  227. package/core/audits/multi-check-audit.d.ts +0 -28
  228. package/core/audits/multi-check-audit.js +0 -82
  229. package/core/audits/no-unload-listeners.d.ts +0 -16
  230. package/core/audits/no-unload-listeners.js +0 -86
  231. package/core/audits/performance-budget.d.ts +0 -39
  232. package/core/audits/performance-budget.js +0 -154
  233. package/core/audits/script-elements-test-audit.d.ts +0 -14
  234. package/core/audits/script-elements-test-audit.js +0 -29
  235. package/core/audits/seo/plugins.d.ts +0 -15
  236. package/core/audits/seo/plugins.js +0 -150
  237. package/core/audits/seo/tap-targets.d.ts +0 -50
  238. package/core/audits/seo/tap-targets.js +0 -352
  239. package/core/audits/splash-screen.d.ts +0 -37
  240. package/core/audits/splash-screen.js +0 -98
  241. package/core/audits/themed-omnibox.d.ts +0 -42
  242. package/core/audits/themed-omnibox.js +0 -102
  243. package/core/audits/timing-budget.d.ts +0 -43
  244. package/core/audits/timing-budget.js +0 -175
  245. package/core/computed/manifest-values.d.ts +0 -24
  246. package/core/computed/manifest-values.js +0 -136
  247. package/core/config/budget.d.ts +0 -74
  248. package/core/config/budget.js +0 -340
  249. package/core/config/metrics-to-audits.d.ts +0 -19
  250. package/core/config/metrics-to-audits.js +0 -62
  251. package/core/gather/driver/service-workers.d.ts +0 -16
  252. package/core/gather/driver/service-workers.js +0 -52
  253. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +0 -47
  254. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +0 -233
  255. package/core/gather/gatherers/global-listeners.d.ts +0 -27
  256. package/core/gather/gatherers/global-listeners.js +0 -108
  257. package/core/gather/gatherers/installability-errors.d.ts +0 -17
  258. package/core/gather/gatherers/installability-errors.js +0 -56
  259. package/core/gather/gatherers/script-elements.d.ts +0 -21
  260. package/core/gather/gatherers/script-elements.js +0 -100
  261. package/core/gather/gatherers/seo/embedded-content.d.ts +0 -10
  262. package/core/gather/gatherers/seo/embedded-content.js +0 -63
  263. package/core/gather/gatherers/seo/tap-targets.d.ts +0 -21
  264. package/core/gather/gatherers/seo/tap-targets.js +0 -389
  265. package/core/gather/gatherers/service-worker.d.ts +0 -10
  266. package/core/gather/gatherers/service-worker.js +0 -32
  267. package/core/gather/gatherers/web-app-manifest.d.ts +0 -32
  268. package/core/gather/gatherers/web-app-manifest.js +0 -106
  269. package/report/renderer/pwa-category-renderer.d.ts +0 -55
  270. package/report/renderer/pwa-category-renderer.js +0 -184
  271. package/third-party/chromium-synchronization/installability-errors-test.js +0 -79
  272. package/types/lhr/budget.d.ts +0 -60
@@ -1,340 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2019 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @param {unknown} arr
9
- * @return {arr is Array<Record<string, unknown>>}
10
- */
11
- function isArrayOfUnknownObjects(arr) {
12
- return Array.isArray(arr) && arr.every(isObjectOfUnknownProperties);
13
- }
14
-
15
- /**
16
- * @param {unknown} val
17
- * @return {val is Record<string, unknown>}
18
- */
19
- function isObjectOfUnknownProperties(val) {
20
- return typeof val === 'object' && val !== null && !Array.isArray(val);
21
- }
22
-
23
- /**
24
- * Returns whether `val` is numeric. Will not coerce to a number. `NaN` will
25
- * return false, however ±Infinity will return true.
26
- * @param {unknown} val
27
- * @return {val is number}
28
- */
29
- function isNumber(val) {
30
- return typeof val === 'number' && !isNaN(val);
31
- }
32
-
33
- class Budget {
34
- /**
35
- * Asserts that obj has no own properties, throwing a nice error message if it does.
36
- * `objectName` is included for nicer logging.
37
- * @param {Record<string, unknown>} obj
38
- * @param {string} objectName
39
- */
40
- static assertNoExcessProperties(obj, objectName) {
41
- const invalidKeys = Object.keys(obj);
42
- if (invalidKeys.length > 0) {
43
- const keys = invalidKeys.join(', ');
44
- throw new Error(`${objectName} has unrecognized properties: [${keys}]`);
45
- }
46
- }
47
-
48
- /**
49
- * Asserts that `strings` has no duplicate strings in it, throwing an error if
50
- * it does. `arrayName` is included for nicer logging.
51
- * @param {Array<string>} strings
52
- * @param {string} arrayName
53
- */
54
- static assertNoDuplicateStrings(strings, arrayName) {
55
- const foundStrings = new Set();
56
- for (const string of strings) {
57
- if (foundStrings.has(string)) {
58
- throw new Error(`${arrayName} has duplicate entry of type '${string}'`);
59
- }
60
- foundStrings.add(string);
61
- }
62
- }
63
-
64
- /**
65
- * @param {Record<string, unknown>} resourceBudget
66
- * @return {LH.Budget.ResourceBudget}
67
- */
68
- static validateResourceBudget(resourceBudget) {
69
- const {resourceType, budget, ...invalidRest} = resourceBudget;
70
- Budget.assertNoExcessProperties(invalidRest, 'Resource Budget');
71
-
72
- /** @type {Array<LH.Budget.ResourceType>} */
73
- const validResourceTypes = [
74
- 'total',
75
- 'document',
76
- 'script',
77
- 'stylesheet',
78
- 'image',
79
- 'media',
80
- 'font',
81
- 'other',
82
- 'third-party',
83
- ];
84
- // Assume resourceType is an allowed string, throw if not.
85
- if (!validResourceTypes.includes(/** @type {LH.Budget.ResourceType} */ (resourceType))) {
86
- throw new Error(`Invalid resource type: ${resourceType}. \n` +
87
- `Valid resource types are: ${validResourceTypes.join(', ') }`);
88
- }
89
- if (!isNumber(budget)) {
90
- throw new Error(`Invalid budget: ${budget}`);
91
- }
92
- return {
93
- resourceType: /** @type {LH.Budget.ResourceType} */ (resourceType),
94
- budget,
95
- };
96
- }
97
-
98
- /**
99
- * @param {unknown} path
100
- * @param {string} error
101
- */
102
- static throwInvalidPathError(path, error) {
103
- throw new Error(`Invalid path ${path}. ${error}\n` +
104
- `'Path' should be specified using the 'robots.txt' format.\n` +
105
- `Learn more about the 'robots.txt' format here:\n` +
106
- `https://developers.google.com/search/reference/robots_txt#url-matching-based-on-path-values`);
107
- }
108
-
109
-
110
- /**
111
- * Validates that path is either: a) undefined or ) properly formed.
112
- * Verifies the quantity and location of the two robot.txt regex characters: $, *
113
- * @param {unknown} path
114
- * @return {undefined|string}
115
- */
116
- static validatePath(path) {
117
- if (path === undefined) {
118
- return undefined;
119
- } else if (typeof path !== 'string') {
120
- this.throwInvalidPathError(path, `Path should be a string.`);
121
- return;
122
- } else if (!path.startsWith('/')) {
123
- this.throwInvalidPathError(path, `Path should start with '/'.`);
124
- } else if ((path.match(/\*/g) || []).length > 1) {
125
- this.throwInvalidPathError(path, `Path should only contain one '*'.`);
126
- } else if ((path.match(/\$/g) || []).length > 1) {
127
- this.throwInvalidPathError(path, `Path should only contain one '$' character.`);
128
- } else if (path.includes('$') && !path.endsWith('$')) {
129
- this.throwInvalidPathError(path, `'$' character should only occur at end of path.`);
130
- }
131
- return path;
132
- }
133
-
134
- /**
135
- * Returns the budget that applies to a given URL.
136
- * If multiple budgets match based on thier 'path' property,
137
- * then the last-listed of those budgets is returned.
138
- * @param {LH.Util.Immutable<Array<LH.Budget>>|null} budgets
139
- * @param {string|undefined} url
140
- * @return {LH.Util.Immutable<LH.Budget> | undefined} budget
141
- */
142
- static getMatchingBudget(budgets, url) {
143
- if (budgets === null || url === undefined) return;
144
-
145
- // Applies the LAST matching budget.
146
- for (let i = budgets.length - 1; i >= 0; i--) {
147
- const budget = budgets[i];
148
- if (this.urlMatchesPattern(url, budget.path)) {
149
- return budget;
150
- }
151
- }
152
- }
153
-
154
- /**
155
- * Determines whether a URL matches against a robots.txt-style "path".
156
- * Pattern should use the robots.txt format. E.g. "/*-article.html" or "/". Reference:
157
- * https://developers.google.com/search/reference/robots_txt#url-matching-based-on-path-values
158
- * @param {string} url
159
- * @param {string=} pattern
160
- * @return {boolean}
161
- */
162
- static urlMatchesPattern(url, pattern = '/') {
163
- const urlObj = new URL(url);
164
- const urlPath = urlObj.pathname + urlObj.search;
165
-
166
- const hasWildcard = pattern.includes('*');
167
- const hasDollarSign = pattern.includes('$');
168
-
169
- /**
170
- * There are 4 different cases of path strings.
171
- * Paths should have already been validated with #validatePath.
172
- *
173
- * Case #1: No special characters
174
- * Example: "/cat"
175
- * Behavior: URL should start with given pattern.
176
- */
177
- if (!hasWildcard && !hasDollarSign) {
178
- return urlPath.startsWith(pattern);
179
- /**
180
- * Case #2: $ only
181
- * Example: "/js$"
182
- * Behavior: URL should be identical to pattern.
183
- */
184
- } else if (!hasWildcard && hasDollarSign) {
185
- return urlPath === pattern.slice(0, -1);
186
- /**
187
- * Case #3: * only
188
- * Example: "/vendor*chunk"
189
- * Behavior: URL should start with the string pattern that comes before the wildcard
190
- * & later in the string contain the string pattern that comes after the wildcard.
191
- */
192
- } else if (hasWildcard && !hasDollarSign) {
193
- const [beforeWildcard, afterWildcard] = pattern.split('*');
194
- const remainingUrl = urlPath.slice(beforeWildcard.length);
195
- return urlPath.startsWith(beforeWildcard) && remainingUrl.includes(afterWildcard);
196
- /**
197
- * Case #4: $ and *
198
- * Example: "/vendor*chunk.js$"
199
- * Behavior: URL should start with the string pattern that comes before the wildcard
200
- * & later in the string end with the string pattern that comes after the wildcard.
201
- */
202
- } else if (hasWildcard && hasDollarSign) {
203
- const [beforeWildcard, afterWildcard] = pattern.split('*');
204
- const urlEnd = urlPath.slice(beforeWildcard.length);
205
- return urlPath.startsWith(beforeWildcard) && urlEnd.endsWith(afterWildcard.slice(0, -1));
206
- }
207
- return false;
208
- }
209
-
210
- /**
211
- * @param {Record<string, unknown>} timingBudget
212
- * @return {LH.Budget.TimingBudget}
213
- */
214
- static validateTimingBudget(timingBudget) {
215
- const {metric, budget, ...invalidRest} = timingBudget;
216
- Budget.assertNoExcessProperties(invalidRest, 'Timing Budget');
217
-
218
- /** @type {Array<LH.Budget.TimingMetric>} */
219
- const validTimingMetrics = [
220
- 'first-contentful-paint',
221
- 'interactive',
222
- 'first-meaningful-paint',
223
- 'max-potential-fid',
224
- 'total-blocking-time',
225
- 'speed-index',
226
- 'largest-contentful-paint',
227
- 'cumulative-layout-shift',
228
- ];
229
- // Assume metric is an allowed string, throw if not.
230
- if (!validTimingMetrics.includes(/** @type {LH.Budget.TimingMetric} */ (metric))) {
231
- throw new Error(`Invalid timing metric: ${metric}. \n` +
232
- `Valid timing metrics are: ${validTimingMetrics.join(', ')}`);
233
- }
234
- if (!isNumber(budget)) {
235
- throw new Error(`Invalid budget: ${budget}`);
236
- }
237
- return {
238
- metric: /** @type {LH.Budget.TimingMetric} */ (metric),
239
- budget,
240
- };
241
- }
242
-
243
- /**
244
- * @param {string} hostname
245
- * @return {string}
246
- */
247
- static validateHostname(hostname) {
248
- const errMsg = `${hostname} is not a valid hostname.`;
249
- if (hostname.length === 0) {
250
- throw new Error(errMsg);
251
- }
252
- if (hostname.includes('/')) {
253
- throw new Error(errMsg);
254
- }
255
- if (hostname.includes(':')) {
256
- throw new Error(errMsg);
257
- }
258
- if (hostname.includes('*')) {
259
- if (!hostname.startsWith('*.') || hostname.lastIndexOf('*') > 0) {
260
- throw new Error(errMsg);
261
- }
262
- }
263
- return hostname;
264
- }
265
-
266
- /**
267
- * @param {unknown} hostnames
268
- * @return {undefined|Array<string>}
269
- */
270
- static validateHostnames(hostnames) {
271
- if (Array.isArray(hostnames) && hostnames.every(host => typeof host === 'string')) {
272
- return hostnames.map(Budget.validateHostname);
273
- } else if (hostnames !== undefined) {
274
- throw new Error(`firstPartyHostnames should be defined as an array of strings.`);
275
- }
276
- }
277
-
278
- /**
279
- * More info on the Budget format:
280
- * https://github.com/GoogleChrome/lighthouse/issues/6053#issuecomment-428385930
281
- * @param {unknown} budgetJson
282
- * @return {Array<LH.Budget>}
283
- */
284
- static initializeBudget(budgetJson) {
285
- // Clone to prevent modifications of original and to deactivate any live properties.
286
- budgetJson = JSON.parse(JSON.stringify(budgetJson));
287
- if (!isArrayOfUnknownObjects(budgetJson)) {
288
- throw new Error('Budget file is not defined as an array of budgets.');
289
- }
290
-
291
- const budgets = budgetJson.map((b, index) => {
292
- /** @type {LH.Budget} */
293
- const budget = {};
294
-
295
- const {path, options, resourceSizes, resourceCounts, timings, ...invalidRest} = b;
296
- Budget.assertNoExcessProperties(invalidRest, 'Budget');
297
-
298
- budget.path = Budget.validatePath(path);
299
-
300
- if (isObjectOfUnknownProperties(options)) {
301
- const {firstPartyHostnames, ...invalidRest} = options;
302
- Budget.assertNoExcessProperties(invalidRest, 'Options property');
303
- budget.options = {};
304
- budget.options.firstPartyHostnames = Budget.validateHostnames(firstPartyHostnames);
305
- } else if (options !== undefined) {
306
- throw new Error(`Invalid options property in budget at index ${index}`);
307
- }
308
-
309
- if (isArrayOfUnknownObjects(resourceSizes)) {
310
- budget.resourceSizes = resourceSizes.map(Budget.validateResourceBudget);
311
- Budget.assertNoDuplicateStrings(budget.resourceSizes.map(r => r.resourceType),
312
- `budgets[${index}].resourceSizes`);
313
- } else if (resourceSizes !== undefined) {
314
- throw new Error(`Invalid resourceSizes entry in budget at index ${index}`);
315
- }
316
-
317
- if (isArrayOfUnknownObjects(resourceCounts)) {
318
- budget.resourceCounts = resourceCounts.map(Budget.validateResourceBudget);
319
- Budget.assertNoDuplicateStrings(budget.resourceCounts.map(r => r.resourceType),
320
- `budgets[${index}].resourceCounts`);
321
- } else if (resourceCounts !== undefined) {
322
- throw new Error(`Invalid resourceCounts entry in budget at index ${index}`);
323
- }
324
-
325
- if (isArrayOfUnknownObjects(timings)) {
326
- budget.timings = timings.map(Budget.validateTimingBudget);
327
- Budget.assertNoDuplicateStrings(budget.timings.map(r => r.metric),
328
- `budgets[${index}].timings`);
329
- } else if (timings !== undefined) {
330
- throw new Error(`Invalid timings entry in budget at index ${index}`);
331
- }
332
-
333
- return budget;
334
- });
335
-
336
- return budgets;
337
- }
338
- }
339
-
340
- export {Budget};
@@ -1,19 +0,0 @@
1
- export namespace metricsToAudits {
2
- export { fcpRelevantAudits };
3
- export { lcpRelevantAudits };
4
- export { tbtRelevantAudits };
5
- export { clsRelevantAudits };
6
- export { inpRelevantAudits };
7
- }
8
- /**
9
- * @license
10
- * Copyright 2021 Google LLC
11
- * SPDX-License-Identifier: Apache-2.0
12
- */
13
- declare const fcpRelevantAudits: string[];
14
- declare const lcpRelevantAudits: string[];
15
- declare const tbtRelevantAudits: string[];
16
- declare const clsRelevantAudits: string[];
17
- declare const inpRelevantAudits: string[];
18
- export {};
19
- //# sourceMappingURL=metrics-to-audits.d.ts.map
@@ -1,62 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- // go/lh-audit-metric-mapping
8
- const fcpRelevantAudits = [
9
- 'server-response-time',
10
- 'render-blocking-resources',
11
- 'redirects',
12
- 'critical-request-chains',
13
- 'uses-text-compression',
14
- 'uses-rel-preconnect',
15
- 'uses-rel-preload',
16
- 'font-display',
17
- 'unminified-javascript',
18
- 'unminified-css',
19
- 'unused-css-rules',
20
- ];
21
-
22
- const lcpRelevantAudits = [
23
- ...fcpRelevantAudits,
24
- 'largest-contentful-paint-element',
25
- 'prioritize-lcp-image',
26
- 'unused-javascript',
27
- 'efficient-animated-content',
28
- 'total-byte-weight',
29
- 'lcp-lazy-loaded',
30
- ];
31
-
32
- const tbtRelevantAudits = [
33
- 'long-tasks',
34
- 'third-party-summary',
35
- 'third-party-facades',
36
- 'bootup-time',
37
- 'mainthread-work-breakdown',
38
- 'dom-size',
39
- 'duplicated-javascript',
40
- 'legacy-javascript',
41
- 'viewport',
42
- ];
43
-
44
- const clsRelevantAudits = [
45
- 'layout-shift-elements',
46
- 'layout-shifts',
47
- 'non-composited-animations',
48
- 'unsized-images',
49
- // 'preload-fonts', // actually in BP, rather than perf
50
- ];
51
-
52
- const inpRelevantAudits = [
53
- 'work-during-interaction',
54
- ];
55
-
56
- export const metricsToAudits = {
57
- fcpRelevantAudits,
58
- lcpRelevantAudits,
59
- tbtRelevantAudits,
60
- clsRelevantAudits,
61
- inpRelevantAudits,
62
- };
@@ -1,16 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- /**
7
- * @param {LH.Gatherer.ProtocolSession} session
8
- * @return {Promise<LH.Crdp.ServiceWorker.WorkerVersionUpdatedEvent>}
9
- */
10
- export function getServiceWorkerVersions(session: LH.Gatherer.ProtocolSession): Promise<LH.Crdp.ServiceWorker.WorkerVersionUpdatedEvent>;
11
- /**
12
- * @param {LH.Gatherer.ProtocolSession} session
13
- * @return {Promise<LH.Crdp.ServiceWorker.WorkerRegistrationUpdatedEvent>}
14
- */
15
- export function getServiceWorkerRegistrations(session: LH.Gatherer.ProtocolSession): Promise<LH.Crdp.ServiceWorker.WorkerRegistrationUpdatedEvent>;
16
- //# sourceMappingURL=service-workers.d.ts.map
@@ -1,52 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @param {LH.Gatherer.ProtocolSession} session
9
- * @return {Promise<LH.Crdp.ServiceWorker.WorkerVersionUpdatedEvent>}
10
- */
11
- function getServiceWorkerVersions(session) {
12
- return new Promise((resolve, reject) => {
13
- /**
14
- * @param {LH.Crdp.ServiceWorker.WorkerVersionUpdatedEvent} data
15
- */
16
- const versionUpdatedListener = data => {
17
- // find a service worker with runningStatus that looks like active
18
- // on slow connections the serviceworker might still be installing
19
- const activateCandidates = data.versions.filter(sw => {
20
- return sw.status !== 'redundant';
21
- });
22
-
23
- const hasActiveServiceWorker = activateCandidates.find(sw => {
24
- return sw.status === 'activated';
25
- });
26
-
27
- if (!activateCandidates.length || hasActiveServiceWorker) {
28
- session.off('ServiceWorker.workerVersionUpdated', versionUpdatedListener);
29
- session.sendCommand('ServiceWorker.disable').then(_ => resolve(data), reject);
30
- }
31
- };
32
-
33
- session.on('ServiceWorker.workerVersionUpdated', versionUpdatedListener);
34
-
35
- session.sendCommand('ServiceWorker.enable').catch(reject);
36
- });
37
- }
38
-
39
- /**
40
- * @param {LH.Gatherer.ProtocolSession} session
41
- * @return {Promise<LH.Crdp.ServiceWorker.WorkerRegistrationUpdatedEvent>}
42
- */
43
- function getServiceWorkerRegistrations(session) {
44
- return new Promise((resolve, reject) => {
45
- session.once('ServiceWorker.workerRegistrationUpdated', data => {
46
- session.sendCommand('ServiceWorker.disable').then(_ => resolve(data), reject);
47
- });
48
- session.sendCommand('ServiceWorker.enable').catch(reject);
49
- });
50
- }
51
-
52
- export {getServiceWorkerVersions, getServiceWorkerRegistrations};
@@ -1,47 +0,0 @@
1
- export default TagsBlockingFirstPaint;
2
- export type MediaChange = {
3
- href: string;
4
- media: string;
5
- msSinceHTMLEnd: number;
6
- matches: boolean;
7
- };
8
- export type LinkTag = {
9
- tagName: 'LINK';
10
- url: string;
11
- href: string;
12
- rel: string;
13
- media: string;
14
- disabled: boolean;
15
- mediaChanges: Array<MediaChange>;
16
- };
17
- export type ScriptTag = {
18
- tagName: 'SCRIPT';
19
- url: string;
20
- src: string;
21
- };
22
- declare class TagsBlockingFirstPaint extends BaseGatherer {
23
- /**
24
- * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
25
- * @return {Map<string, LH.Artifacts.NetworkRequest>}
26
- */
27
- static _filteredAndIndexedByUrl(networkRecords: Array<LH.Artifacts.NetworkRequest>): Map<string, LH.Artifacts.NetworkRequest>;
28
- /**
29
- * @param {LH.Gatherer.Driver} driver
30
- * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
31
- * @return {Promise<Array<LH.Artifacts.TagBlockingFirstPaint>>}
32
- */
33
- static findBlockingTags(driver: LH.Gatherer.Driver, networkRecords: Array<LH.Artifacts.NetworkRequest>): Promise<Array<LH.Artifacts.TagBlockingFirstPaint>>;
34
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
35
- meta: LH.Gatherer.GathererMeta<'DevtoolsLog'>;
36
- /**
37
- * @param {LH.Gatherer.Context} context
38
- */
39
- startSensitiveInstrumentation(context: LH.Gatherer.Context): Promise<void>;
40
- /**
41
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} context
42
- * @return {Promise<LH.Artifacts['TagsBlockingFirstPaint']>}
43
- */
44
- getArtifact(context: LH.Gatherer.Context<'DevtoolsLog'>): Promise<LH.Artifacts['TagsBlockingFirstPaint']>;
45
- }
46
- import BaseGatherer from '../../base-gatherer.js';
47
- //# sourceMappingURL=tags-blocking-first-paint.d.ts.map