lighthouse 12.8.2 → 13.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 (270) hide show
  1. package/cli/cli-flags.js +1 -1
  2. package/cli/test/smokehouse/config/exclusions.js +0 -2
  3. package/cli/test/smokehouse/version-check.d.ts +1 -1
  4. package/core/audits/accessibility/accesskeys.js +3 -3
  5. package/core/audits/accessibility/aria-allowed-attr.js +3 -3
  6. package/core/audits/accessibility/aria-allowed-role.js +2 -1
  7. package/core/audits/accessibility/aria-command-name.js +1 -1
  8. package/core/audits/accessibility/aria-conditional-attr.js +1 -1
  9. package/core/audits/accessibility/aria-deprecated-role.js +1 -1
  10. package/core/audits/accessibility/aria-dialog-name.js +1 -1
  11. package/core/audits/accessibility/aria-hidden-body.js +3 -3
  12. package/core/audits/accessibility/aria-hidden-focus.js +3 -3
  13. package/core/audits/accessibility/aria-input-field-name.js +3 -3
  14. package/core/audits/accessibility/aria-meter-name.js +1 -1
  15. package/core/audits/accessibility/aria-progressbar-name.js +1 -1
  16. package/core/audits/accessibility/aria-prohibited-attr.js +1 -1
  17. package/core/audits/accessibility/aria-required-attr.js +3 -3
  18. package/core/audits/accessibility/aria-required-children.js +3 -3
  19. package/core/audits/accessibility/aria-required-parent.js +3 -3
  20. package/core/audits/accessibility/aria-roles.js +3 -3
  21. package/core/audits/accessibility/aria-text.js +3 -3
  22. package/core/audits/accessibility/aria-toggle-field-name.js +3 -3
  23. package/core/audits/accessibility/aria-tooltip-name.js +1 -1
  24. package/core/audits/accessibility/aria-treeitem-name.js +1 -1
  25. package/core/audits/accessibility/aria-valid-attr-value.js +3 -3
  26. package/core/audits/accessibility/aria-valid-attr.js +3 -3
  27. package/core/audits/accessibility/button-name.js +3 -3
  28. package/core/audits/accessibility/bypass.js +3 -3
  29. package/core/audits/accessibility/color-contrast.js +3 -3
  30. package/core/audits/accessibility/definition-list.js +3 -3
  31. package/core/audits/accessibility/dlitem.js +3 -3
  32. package/core/audits/accessibility/document-title.js +3 -3
  33. package/core/audits/accessibility/duplicate-id-aria.js +3 -3
  34. package/core/audits/accessibility/empty-heading.js +3 -3
  35. package/core/audits/accessibility/form-field-multiple-labels.js +3 -3
  36. package/core/audits/accessibility/frame-title.js +3 -3
  37. package/core/audits/accessibility/heading-order.js +3 -3
  38. package/core/audits/accessibility/html-has-lang.js +3 -3
  39. package/core/audits/accessibility/html-lang-valid.js +3 -3
  40. package/core/audits/accessibility/html-xml-lang-mismatch.js +3 -3
  41. package/core/audits/accessibility/identical-links-same-purpose.js +3 -3
  42. package/core/audits/accessibility/image-alt.js +3 -3
  43. package/core/audits/accessibility/image-redundant-alt.js +4 -3
  44. package/core/audits/accessibility/input-button-name.js +3 -3
  45. package/core/audits/accessibility/input-image-alt.js +3 -3
  46. package/core/audits/accessibility/label-content-name-mismatch.js +3 -3
  47. package/core/audits/accessibility/label.js +3 -3
  48. package/core/audits/accessibility/landmark-one-main.js +3 -4
  49. package/core/audits/accessibility/link-in-text-block.js +3 -3
  50. package/core/audits/accessibility/link-name.js +3 -3
  51. package/core/audits/accessibility/list.js +3 -3
  52. package/core/audits/accessibility/listitem.js +3 -3
  53. package/core/audits/accessibility/meta-refresh.js +3 -3
  54. package/core/audits/accessibility/meta-viewport.js +3 -3
  55. package/core/audits/accessibility/object-alt.js +3 -3
  56. package/core/audits/accessibility/select-name.js +3 -3
  57. package/core/audits/accessibility/skip-link.js +3 -3
  58. package/core/audits/accessibility/tabindex.js +3 -3
  59. package/core/audits/accessibility/table-duplicate-name.js +4 -3
  60. package/core/audits/accessibility/table-fake-caption.js +3 -3
  61. package/core/audits/accessibility/target-size.js +3 -3
  62. package/core/audits/accessibility/td-has-header.js +3 -3
  63. package/core/audits/accessibility/td-headers-attr.js +3 -3
  64. package/core/audits/accessibility/th-has-data-cells.js +3 -3
  65. package/core/audits/accessibility/valid-lang.js +3 -3
  66. package/core/audits/accessibility/video-caption.js +3 -3
  67. package/core/audits/audit.d.ts +0 -4
  68. package/core/audits/audit.js +2 -13
  69. package/core/audits/insights/cls-culprits-insight.js +1 -1
  70. package/core/audits/insights/dom-size-insight.js +11 -7
  71. package/core/audits/insights/font-display-insight.js +3 -1
  72. package/core/audits/insights/image-delivery-insight.js +4 -1
  73. package/core/audits/insights/insight-audit.d.ts +6 -4
  74. package/core/audits/insights/insight-audit.js +27 -8
  75. package/core/audits/insights/third-parties-insight.js +1 -1
  76. package/core/audits/layout-shifts.js +1 -1
  77. package/core/audits/predictive-perf.js +2 -2
  78. package/core/audits/seo/crawlable-anchors.js +2 -3
  79. package/core/audits/seo/manual/structured-data.js +1 -1
  80. package/core/audits/server-response-time.d.ts +0 -5
  81. package/core/audits/server-response-time.js +12 -26
  82. package/core/computed/metrics/cumulative-layout-shift.js +2 -2
  83. package/core/computed/metrics/lantern-metric.js +3 -3
  84. package/core/computed/metrics/lcp-breakdown.d.ts +10 -5
  85. package/core/computed/metrics/lcp-breakdown.js +50 -22
  86. package/core/computed/metrics/time-to-first-byte.js +33 -10
  87. package/core/computed/metrics/timing-summary.js +3 -2
  88. package/core/computed/page-dependency-graph.js +1 -1
  89. package/core/computed/trace-engine-result.js +2 -2
  90. package/core/config/default-config.js +110 -152
  91. package/core/config/experimental-config.js +1 -32
  92. package/core/config/filters.js +6 -9
  93. package/core/config/lr-desktop-config.js +0 -1
  94. package/core/config/lr-mobile-config.js +0 -1
  95. package/core/gather/driver/target-manager.d.ts +1 -1
  96. package/core/gather/driver.d.ts +1 -1
  97. package/core/gather/gatherers/anchor-elements.js +8 -24
  98. package/core/gather/gatherers/image-elements.js +32 -6
  99. package/core/gather/gatherers/inspector-issues.js +1 -28
  100. package/core/gather/gatherers/trace-elements.d.ts +2 -11
  101. package/core/gather/gatherers/trace-elements.js +9 -39
  102. package/core/gather/navigation-runner.js +0 -3
  103. package/core/gather/session.d.ts +1 -1
  104. package/core/lib/asset-saver.d.ts +2 -2
  105. package/core/lib/asset-saver.js +33 -43
  106. package/core/lib/bf-cache-strings.js +10 -9
  107. package/core/lib/deprecations-strings.js +5 -5
  108. package/core/lib/emulation.d.ts +10 -0
  109. package/core/lib/emulation.js +21 -6
  110. package/core/lib/legacy-javascript/legacy-javascript.js +4 -11
  111. package/core/lib/network-request.d.ts +0 -7
  112. package/core/lib/network-request.js +0 -16
  113. package/core/lib/proto-preprocessor.js +10 -25
  114. package/core/runner.js +1 -8
  115. package/core/scoring.js +1 -1
  116. package/dist/report/bundle.esm.js +10 -49
  117. package/dist/report/flow.js +12 -51
  118. package/dist/report/standalone.js +11 -50
  119. package/flow-report/src/i18n/i18n.d.ts +4 -6
  120. package/package.json +16 -19
  121. package/readme.md +2 -2
  122. package/report/assets/styles.css +0 -39
  123. package/report/renderer/api.js +0 -1
  124. package/report/renderer/category-renderer.js +6 -0
  125. package/report/renderer/components.js +1 -1
  126. package/report/renderer/details-renderer.d.ts +1 -2
  127. package/report/renderer/details-renderer.js +0 -1
  128. package/report/renderer/dom.d.ts +0 -13
  129. package/report/renderer/dom.js +0 -38
  130. package/report/renderer/performance-category-renderer.d.ts +0 -26
  131. package/report/renderer/performance-category-renderer.js +10 -142
  132. package/report/renderer/report-ui-features.d.ts +0 -1
  133. package/report/renderer/report-ui-features.js +2 -13
  134. package/report/renderer/report-utils.d.ts +2 -3
  135. package/report/renderer/report-utils.js +4 -6
  136. package/report/types/report-renderer.d.ts +0 -6
  137. package/shared/localization/locales/ar-XB.json +107 -455
  138. package/shared/localization/locales/ar.json +107 -455
  139. package/shared/localization/locales/bg.json +96 -444
  140. package/shared/localization/locales/ca.json +96 -444
  141. package/shared/localization/locales/cs.json +96 -444
  142. package/shared/localization/locales/da.json +96 -444
  143. package/shared/localization/locales/de.json +96 -444
  144. package/shared/localization/locales/el.json +96 -444
  145. package/shared/localization/locales/en-GB.json +96 -444
  146. package/shared/localization/locales/en-US.json +116 -467
  147. package/shared/localization/locales/en-XA.json +93 -441
  148. package/shared/localization/locales/en-XL.json +116 -467
  149. package/shared/localization/locales/es-419.json +96 -444
  150. package/shared/localization/locales/es.json +96 -444
  151. package/shared/localization/locales/fi.json +96 -444
  152. package/shared/localization/locales/fil.json +96 -444
  153. package/shared/localization/locales/fr.json +96 -444
  154. package/shared/localization/locales/he.json +118 -466
  155. package/shared/localization/locales/hi.json +96 -444
  156. package/shared/localization/locales/hr.json +100 -448
  157. package/shared/localization/locales/hu.json +96 -444
  158. package/shared/localization/locales/id.json +96 -444
  159. package/shared/localization/locales/it.json +96 -444
  160. package/shared/localization/locales/ja.json +96 -444
  161. package/shared/localization/locales/ko.json +97 -445
  162. package/shared/localization/locales/lt.json +96 -444
  163. package/shared/localization/locales/lv.json +97 -445
  164. package/shared/localization/locales/nl.json +96 -444
  165. package/shared/localization/locales/no.json +96 -444
  166. package/shared/localization/locales/pl.json +96 -444
  167. package/shared/localization/locales/pt-PT.json +96 -444
  168. package/shared/localization/locales/pt.json +97 -445
  169. package/shared/localization/locales/ro.json +97 -445
  170. package/shared/localization/locales/ru.json +96 -444
  171. package/shared/localization/locales/sk.json +96 -444
  172. package/shared/localization/locales/sl.json +96 -444
  173. package/shared/localization/locales/sr-Latn.json +96 -444
  174. package/shared/localization/locales/sr.json +96 -444
  175. package/shared/localization/locales/sv.json +96 -444
  176. package/shared/localization/locales/ta.json +96 -444
  177. package/shared/localization/locales/te.json +97 -445
  178. package/shared/localization/locales/th.json +96 -444
  179. package/shared/localization/locales/tr.json +96 -444
  180. package/shared/localization/locales/uk.json +96 -444
  181. package/shared/localization/locales/vi.json +96 -444
  182. package/shared/localization/locales/zh-HK.json +96 -444
  183. package/shared/localization/locales/zh-TW.json +97 -445
  184. package/shared/localization/locales/zh.json +96 -444
  185. package/shared/localization/locales.d.ts +2 -0
  186. package/shared/localization/locales.js +130 -139
  187. package/shared/tsconfig.json +2 -0
  188. package/tsconfig-base.json +2 -2
  189. package/tsconfig.json +1 -4
  190. package/types/artifacts.d.ts +6 -81
  191. package/types/audit.d.ts +1 -1
  192. package/types/lhr/settings.d.ts +1 -1
  193. package/core/audits/byte-efficiency/duplicated-javascript.d.ts +0 -45
  194. package/core/audits/byte-efficiency/duplicated-javascript.js +0 -223
  195. package/core/audits/byte-efficiency/efficient-animated-content.d.ts +0 -22
  196. package/core/audits/byte-efficiency/efficient-animated-content.js +0 -93
  197. package/core/audits/byte-efficiency/legacy-javascript.d.ts +0 -28
  198. package/core/audits/byte-efficiency/legacy-javascript.js +0 -144
  199. package/core/audits/byte-efficiency/modern-image-formats.d.ts +0 -38
  200. package/core/audits/byte-efficiency/modern-image-formats.js +0 -187
  201. package/core/audits/byte-efficiency/offscreen-images.d.ts +0 -63
  202. package/core/audits/byte-efficiency/offscreen-images.js +0 -240
  203. package/core/audits/byte-efficiency/render-blocking-resources.d.ts +0 -53
  204. package/core/audits/byte-efficiency/render-blocking-resources.js +0 -312
  205. package/core/audits/byte-efficiency/uses-long-cache-ttl.d.ts +0 -59
  206. package/core/audits/byte-efficiency/uses-long-cache-ttl.js +0 -293
  207. package/core/audits/byte-efficiency/uses-optimized-images.d.ts +0 -33
  208. package/core/audits/byte-efficiency/uses-optimized-images.js +0 -146
  209. package/core/audits/byte-efficiency/uses-responsive-images-snapshot.d.ts +0 -16
  210. package/core/audits/byte-efficiency/uses-responsive-images-snapshot.js +0 -106
  211. package/core/audits/byte-efficiency/uses-responsive-images.d.ts +0 -44
  212. package/core/audits/byte-efficiency/uses-responsive-images.js +0 -202
  213. package/core/audits/byte-efficiency/uses-text-compression.d.ts +0 -14
  214. package/core/audits/byte-efficiency/uses-text-compression.js +0 -108
  215. package/core/audits/critical-request-chains.d.ts +0 -44
  216. package/core/audits/critical-request-chains.js +0 -221
  217. package/core/audits/dobetterweb/dom-size.d.ts +0 -32
  218. package/core/audits/dobetterweb/dom-size.js +0 -182
  219. package/core/audits/dobetterweb/no-document-write.d.ts +0 -16
  220. package/core/audits/dobetterweb/no-document-write.js +0 -86
  221. package/core/audits/dobetterweb/uses-http2.d.ts +0 -72
  222. package/core/audits/dobetterweb/uses-http2.js +0 -276
  223. package/core/audits/dobetterweb/uses-passive-event-listeners.d.ts +0 -16
  224. package/core/audits/dobetterweb/uses-passive-event-listeners.js +0 -69
  225. package/core/audits/font-display.d.ts +0 -32
  226. package/core/audits/font-display.js +0 -195
  227. package/core/audits/largest-contentful-paint-element.d.ts +0 -34
  228. package/core/audits/largest-contentful-paint-element.js +0 -181
  229. package/core/audits/lcp-lazy-loaded.d.ts +0 -22
  230. package/core/audits/lcp-lazy-loaded.js +0 -115
  231. package/core/audits/metrics/first-meaningful-paint.d.ts +0 -12
  232. package/core/audits/metrics/first-meaningful-paint.js +0 -47
  233. package/core/audits/preload-fonts.d.ts +0 -25
  234. package/core/audits/preload-fonts.js +0 -97
  235. package/core/audits/prioritize-lcp-image.d.ts +0 -74
  236. package/core/audits/prioritize-lcp-image.js +0 -297
  237. package/core/audits/seo/font-size.d.ts +0 -24
  238. package/core/audits/seo/font-size.js +0 -344
  239. package/core/audits/third-party-facades.d.ts +0 -41
  240. package/core/audits/third-party-facades.js +0 -234
  241. package/core/audits/third-party-summary.d.ts +0 -78
  242. package/core/audits/third-party-summary.js +0 -236
  243. package/core/audits/uses-rel-preconnect.d.ts +0 -37
  244. package/core/audits/uses-rel-preconnect.js +0 -286
  245. package/core/audits/uses-rel-preload.d.ts +0 -57
  246. package/core/audits/uses-rel-preload.js +0 -263
  247. package/core/audits/viewport.d.ts +0 -17
  248. package/core/audits/viewport.js +0 -87
  249. package/core/audits/work-during-interaction.d.ts +0 -81
  250. package/core/audits/work-during-interaction.js +0 -287
  251. package/core/computed/critical-request-chains.d.ts +0 -42
  252. package/core/computed/critical-request-chains.js +0 -143
  253. package/core/computed/viewport-meta.d.ts +0 -37
  254. package/core/computed/viewport-meta.js +0 -71
  255. package/core/gather/gatherers/cache-contents.d.ts +0 -11
  256. package/core/gather/gatherers/cache-contents.js +0 -56
  257. package/core/gather/gatherers/devtools-log-compat.d.ts +0 -13
  258. package/core/gather/gatherers/devtools-log-compat.js +0 -35
  259. package/core/gather/gatherers/dobetterweb/domstats.d.ts +0 -10
  260. package/core/gather/gatherers/dobetterweb/domstats.js +0 -102
  261. package/core/gather/gatherers/dobetterweb/optimized-images.d.ts +0 -48
  262. package/core/gather/gatherers/dobetterweb/optimized-images.js +0 -169
  263. package/core/gather/gatherers/dobetterweb/response-compression.d.ts +0 -23
  264. package/core/gather/gatherers/dobetterweb/response-compression.js +0 -136
  265. package/core/gather/gatherers/seo/font-size.d.ts +0 -131
  266. package/core/gather/gatherers/seo/font-size.js +0 -347
  267. package/core/gather/gatherers/trace-compat.d.ts +0 -13
  268. package/core/gather/gatherers/trace-compat.js +0 -35
  269. package/types/internal/metaviewport-parser.d.ts +0 -13
  270. package/types/internal/parse-cache-control.d.ts +0 -20
@@ -1,71 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2019 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import Parser from 'metaviewport-parser';
8
-
9
- import {makeComputedArtifact} from './computed-artifact.js';
10
-
11
- class ViewportMeta {
12
- /**
13
- * @param {LH.GathererArtifacts['MetaElements']} MetaElements
14
- * @return {Promise<ViewportMetaResult>}
15
- */
16
- static async compute_(MetaElements) {
17
- const viewportMeta = MetaElements.find(meta => meta.name === 'viewport');
18
-
19
- if (!viewportMeta) {
20
- return {
21
- hasViewportTag: false,
22
- isMobileOptimized: false,
23
- parserWarnings: [],
24
- rawContentString: undefined,
25
- };
26
- }
27
-
28
- const warnings = [];
29
- const rawContentString = viewportMeta.content || '';
30
- const parsedProps = Parser.parseMetaViewPortContent(rawContentString);
31
-
32
- if (Object.keys(parsedProps.unknownProperties).length) {
33
- warnings.push(`Invalid properties found: ${JSON.stringify(parsedProps.unknownProperties)}`);
34
- }
35
- if (Object.keys(parsedProps.invalidValues).length) {
36
- warnings.push(`Invalid values found: ${JSON.stringify(parsedProps.invalidValues)}`);
37
- }
38
-
39
- const viewportProps = parsedProps.validProperties;
40
- const initialScale = Number(viewportProps['initial-scale']);
41
-
42
- if (!isNaN(initialScale) && initialScale < 1) {
43
- return {
44
- hasViewportTag: true,
45
- isMobileOptimized: false,
46
- parserWarnings: warnings,
47
- rawContentString,
48
- };
49
- }
50
-
51
- const isMobileOptimized = Boolean(viewportProps.width || initialScale);
52
-
53
- return {
54
- hasViewportTag: true,
55
- isMobileOptimized,
56
- parserWarnings: warnings,
57
- rawContentString,
58
- };
59
- }
60
- }
61
-
62
- const ViewportMetaComputed = makeComputedArtifact(ViewportMeta, null);
63
- export {ViewportMetaComputed as ViewportMeta};
64
-
65
- /**
66
- * @typedef {object} ViewportMetaResult
67
- * @property {boolean} hasViewportTag Whether the page has any viewport tag.
68
- * @property {boolean} isMobileOptimized Whether the viewport tag is optimized for mobile screens.
69
- * @property {Array<string>} parserWarnings Warnings if the parser encountered invalid content in the viewport tag.
70
- * @property {string|undefined} rawContentString The `content` attribute value, if a viewport was defined.
71
- */
@@ -1,11 +0,0 @@
1
- export default CacheContents;
2
- declare class CacheContents extends BaseGatherer {
3
- /**
4
- * Creates an array of cached URLs.
5
- * @param {LH.Gatherer.Context} passContext
6
- * @return {Promise<LH.Artifacts['CacheContents']>}
7
- */
8
- getArtifact(passContext: LH.Gatherer.Context): Promise<LH.Artifacts["CacheContents"]>;
9
- }
10
- import BaseGatherer from '../base-gatherer.js';
11
- //# sourceMappingURL=cache-contents.d.ts.map
@@ -1,56 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- import BaseGatherer from '../base-gatherer.js';
8
-
9
- /**
10
- * @return {Promise<Array<string>>}
11
- */
12
- /* c8 ignore start */
13
- function getCacheContents() {
14
- // Get every cache by name.
15
- return caches.keys()
16
-
17
- // Open each one.
18
- .then(cacheNames => Promise.all(cacheNames.map(cacheName => caches.open(cacheName))))
19
-
20
- .then(caches => {
21
- /** @type {Array<string>} */
22
- const requests = [];
23
-
24
- // Take each cache and get any requests is contains, and bounce each one down to its URL.
25
- return Promise.all(caches.map(cache => {
26
- return cache.keys()
27
- .then(reqs => {
28
- requests.push(...reqs.map(r => r.url));
29
- });
30
- })).then(_ => {
31
- return requests;
32
- });
33
- });
34
- }
35
- /* c8 ignore stop */
36
-
37
- class CacheContents extends BaseGatherer {
38
- /** @type {LH.Gatherer.GathererMeta} */
39
- meta = {
40
- supportedModes: ['snapshot', 'navigation'],
41
- };
42
-
43
- /**
44
- * Creates an array of cached URLs.
45
- * @param {LH.Gatherer.Context} passContext
46
- * @return {Promise<LH.Artifacts['CacheContents']>}
47
- */
48
- async getArtifact(passContext) {
49
- const driver = passContext.driver;
50
-
51
- const cacheUrls = await driver.executionContext.evaluate(getCacheContents, {args: []});
52
- return cacheUrls;
53
- }
54
- }
55
-
56
- export default CacheContents;
@@ -1,13 +0,0 @@
1
- export default DevtoolsLogCompat;
2
- /** @implements {LH.Gatherer.GathererInstance<'DevtoolsLog'>} */
3
- declare class DevtoolsLogCompat extends BaseGatherer implements LH.Gatherer.GathererInstance<"DevtoolsLog"> {
4
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
5
- meta: LH.Gatherer.GathererMeta<"DevtoolsLog">;
6
- /**
7
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} passContext
8
- * @return {Promise<LH.Artifacts['devtoolsLogs']>}
9
- */
10
- getArtifact(passContext: LH.Gatherer.Context<"DevtoolsLog">): Promise<LH.Artifacts["devtoolsLogs"]>;
11
- }
12
- import BaseGatherer from '../base-gatherer.js';
13
- //# sourceMappingURL=devtools-log-compat.d.ts.map
@@ -1,35 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2021 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @fileoverview
9
- * This gatherer remaps the result of the DevtoolsLog gatherer for compatibility with legacy Lighthouse
10
- * when devtools logs and traces were special-cased.
11
- */
12
-
13
- import DevtoolsLogGatherer from './devtools-log.js';
14
- import BaseGatherer from '../base-gatherer.js';
15
-
16
- /** @implements {LH.Gatherer.GathererInstance<'DevtoolsLog'>} */
17
- class DevtoolsLogCompat extends BaseGatherer {
18
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
19
- meta = {
20
- supportedModes: ['timespan', 'navigation'],
21
- dependencies: {DevtoolsLog: DevtoolsLogGatherer.symbol},
22
- };
23
-
24
- /**
25
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} passContext
26
- * @return {Promise<LH.Artifacts['devtoolsLogs']>}
27
- */
28
- async getArtifact(passContext) {
29
- return {
30
- defaultPass: passContext.dependencies.DevtoolsLog,
31
- };
32
- }
33
- }
34
-
35
- export default DevtoolsLogCompat;
@@ -1,10 +0,0 @@
1
- export default DOMStats;
2
- declare class DOMStats extends BaseGatherer {
3
- /**
4
- * @param {LH.Gatherer.Context} passContext
5
- * @return {Promise<LH.Artifacts['DOMStats']>}
6
- */
7
- getArtifact(passContext: LH.Gatherer.Context): Promise<LH.Artifacts["DOMStats"]>;
8
- }
9
- import BaseGatherer from '../../base-gatherer.js';
10
- //# sourceMappingURL=domstats.d.ts.map
@@ -1,102 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2017 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @fileoverview Gathers stats about the max height and width of the DOM tree
9
- * and total number of elements used on the page.
10
- */
11
-
12
- /* global getNodeDetails */
13
-
14
-
15
- import BaseGatherer from '../../base-gatherer.js';
16
- import {pageFunctions} from '../../../lib/page-functions.js';
17
-
18
- /**
19
- * Calculates the maximum tree depth of the DOM.
20
- * @param {HTMLElement} element Root of the tree to look in.
21
- * @param {boolean=} deep True to include shadow roots. Defaults to true.
22
- * @return {LH.Artifacts.DOMStats}
23
- */
24
- /* c8 ignore start */
25
- function getDOMStats(element = document.body, deep = true) {
26
- let deepestElement = null;
27
- let maxDepth = -1;
28
- let maxWidth = -1;
29
- let numElements = 0;
30
- let parentWithMostChildren = null;
31
-
32
- /**
33
- * @param {Element|ShadowRoot} element
34
- * @param {number} depth
35
- */
36
- const _calcDOMWidthAndHeight = function(element, depth = 1) {
37
- if (depth > maxDepth) {
38
- deepestElement = element;
39
- maxDepth = depth;
40
- }
41
- if (element.children.length > maxWidth) {
42
- parentWithMostChildren = element;
43
- maxWidth = element.children.length;
44
- }
45
-
46
- let child = element.firstElementChild;
47
- while (child) {
48
- _calcDOMWidthAndHeight(child, depth + 1);
49
- // If element has shadow dom, traverse into that tree.
50
- if (deep && child.shadowRoot) {
51
- _calcDOMWidthAndHeight(child.shadowRoot, depth + 1);
52
- }
53
- child = child.nextElementSibling;
54
- numElements++;
55
- }
56
-
57
- return {maxDepth, maxWidth, numElements};
58
- };
59
-
60
- const result = _calcDOMWidthAndHeight(element);
61
-
62
- return {
63
- depth: {
64
- max: result.maxDepth,
65
- // @ts-expect-error - getNodeDetails put into scope via stringification
66
- ...getNodeDetails(deepestElement),
67
- },
68
- width: {
69
- max: result.maxWidth,
70
- // @ts-expect-error - getNodeDetails put into scope via stringification
71
- ...getNodeDetails(parentWithMostChildren),
72
- },
73
- totalBodyElements: result.numElements,
74
- };
75
- }
76
- /* c8 ignore stop */
77
-
78
- class DOMStats extends BaseGatherer {
79
- /** @type {LH.Gatherer.GathererMeta} */
80
- meta = {
81
- supportedModes: ['snapshot', 'navigation'],
82
- };
83
-
84
- /**
85
- * @param {LH.Gatherer.Context} passContext
86
- * @return {Promise<LH.Artifacts['DOMStats']>}
87
- */
88
- async getArtifact(passContext) {
89
- const driver = passContext.driver;
90
-
91
- await driver.defaultSession.sendCommand('DOM.enable');
92
- const results = await driver.executionContext.evaluate(getDOMStats, {
93
- args: [],
94
- useIsolation: true,
95
- deps: [pageFunctions.getNodeDetails],
96
- });
97
- await driver.defaultSession.sendCommand('DOM.disable');
98
- return results;
99
- }
100
- }
101
-
102
- export default DOMStats;
@@ -1,48 +0,0 @@
1
- export default OptimizedImages;
2
- export type SimplifiedNetworkRecord = {
3
- requestId: string;
4
- url: string;
5
- mimeType: string;
6
- resourceSize: number;
7
- };
8
- /** @typedef {{requestId: string, url: string, mimeType: string, resourceSize: number}} SimplifiedNetworkRecord */
9
- declare class OptimizedImages extends BaseGatherer {
10
- /**
11
- * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
12
- * @return {Array<SimplifiedNetworkRecord>}
13
- */
14
- static filterImageRequests(networkRecords: Array<LH.Artifacts.NetworkRequest>): Array<SimplifiedNetworkRecord>;
15
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
16
- meta: LH.Gatherer.GathererMeta<"DevtoolsLog">;
17
- _encodingStartAt: number;
18
- /**
19
- * @param {LH.Gatherer.ProtocolSession} session
20
- * @param {string} requestId
21
- * @param {'jpeg'|'webp'} encoding Either webp or jpeg.
22
- * @return {Promise<LH.Crdp.Audits.GetEncodedResponseResponse>}
23
- */
24
- _getEncodedResponse(session: LH.Gatherer.ProtocolSession, requestId: string, encoding: "jpeg" | "webp"): Promise<LH.Crdp.Audits.GetEncodedResponseResponse>;
25
- /**
26
- * @param {LH.Gatherer.ProtocolSession} session
27
- * @param {SimplifiedNetworkRecord} networkRecord
28
- * @return {Promise<{originalSize: number, jpegSize?: number, webpSize?: number}>}
29
- */
30
- calculateImageStats(session: LH.Gatherer.ProtocolSession, networkRecord: SimplifiedNetworkRecord): Promise<{
31
- originalSize: number;
32
- jpegSize?: number;
33
- webpSize?: number;
34
- }>;
35
- /**
36
- * @param {LH.Gatherer.ProtocolSession} session
37
- * @param {Array<SimplifiedNetworkRecord>} imageRecords
38
- * @return {Promise<LH.Artifacts['OptimizedImages']>}
39
- */
40
- computeOptimizedImages(session: LH.Gatherer.ProtocolSession, imageRecords: Array<SimplifiedNetworkRecord>): Promise<LH.Artifacts["OptimizedImages"]>;
41
- /**
42
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} context
43
- * @return {Promise<LH.Artifacts['OptimizedImages']>}
44
- */
45
- getArtifact(context: LH.Gatherer.Context<"DevtoolsLog">): Promise<LH.Artifacts["OptimizedImages"]>;
46
- }
47
- import BaseGatherer from '../../base-gatherer.js';
48
- //# sourceMappingURL=optimized-images.d.ts.map
@@ -1,169 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2017 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @fileoverview Determines optimized jpeg/webp filesizes for all same-origin and dataURI images
9
- */
10
-
11
- import log from 'lighthouse-logger';
12
-
13
- import BaseGatherer from '../../base-gatherer.js';
14
- import UrlUtils from '../../../lib/url-utils.js';
15
- import {NetworkRequest} from '../../../lib/network-request.js';
16
- import {Sentry} from '../../../lib/sentry.js';
17
- import {NetworkRecords} from '../../../computed/network-records.js';
18
- import DevtoolsLog from '../devtools-log.js';
19
-
20
- // Image encoding can be slow and we don't want to spend forever on it.
21
- // Cap our encoding to 5 seconds, anything after that will be estimated.
22
- const MAX_TIME_TO_SPEND_ENCODING = 5000;
23
- // Cap our image file size at 2MB, anything bigger than that will be estimated.
24
- const MAX_RESOURCE_SIZE_TO_ENCODE = 2000 * 1024;
25
-
26
- const JPEG_QUALITY = 0.92;
27
- const WEBP_QUALITY = 0.85;
28
-
29
- const MINIMUM_IMAGE_SIZE = 4096; // savings of <4 KiB will be ignored in the audit anyway
30
-
31
- const IMAGE_REGEX = /^image\/((x|ms|x-ms)-)?(png|bmp|jpeg)$/;
32
-
33
- /** @typedef {{requestId: string, url: string, mimeType: string, resourceSize: number}} SimplifiedNetworkRecord */
34
-
35
- class OptimizedImages extends BaseGatherer {
36
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
37
- meta = {
38
- supportedModes: ['timespan', 'navigation'],
39
- dependencies: {DevtoolsLog: DevtoolsLog.symbol},
40
- };
41
-
42
- constructor() {
43
- super();
44
- this._encodingStartAt = 0;
45
- }
46
-
47
- /**
48
- * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
49
- * @return {Array<SimplifiedNetworkRecord>}
50
- */
51
- static filterImageRequests(networkRecords) {
52
- /** @type {Set<string>} */
53
- const seenUrls = new Set();
54
- return networkRecords.reduce((prev, record) => {
55
- // Skip records that we've seen before, never finished, or came from OOPIFs/web workers.
56
- if (seenUrls.has(record.url) || !record.finished || record.sessionTargetType !== 'page') {
57
- return prev;
58
- }
59
-
60
- seenUrls.add(record.url);
61
- const isOptimizableImage = record.resourceType === NetworkRequest.TYPES.Image &&
62
- IMAGE_REGEX.test(record.mimeType);
63
-
64
- const actualResourceSize = NetworkRequest.getResourceSizeOnNetwork(record);
65
- if (isOptimizableImage && actualResourceSize > MINIMUM_IMAGE_SIZE) {
66
- prev.push({
67
- requestId: record.requestId,
68
- url: record.url,
69
- mimeType: record.mimeType,
70
- resourceSize: actualResourceSize,
71
- });
72
- }
73
-
74
- return prev;
75
- }, /** @type {Array<SimplifiedNetworkRecord>} */ ([]));
76
- }
77
-
78
- /**
79
- * @param {LH.Gatherer.ProtocolSession} session
80
- * @param {string} requestId
81
- * @param {'jpeg'|'webp'} encoding Either webp or jpeg.
82
- * @return {Promise<LH.Crdp.Audits.GetEncodedResponseResponse>}
83
- */
84
- _getEncodedResponse(session, requestId, encoding) {
85
- requestId = NetworkRequest.getRequestIdForBackend(requestId);
86
-
87
- const quality = encoding === 'jpeg' ? JPEG_QUALITY : WEBP_QUALITY;
88
- const params = {requestId, encoding, quality, sizeOnly: true};
89
- return session.sendCommand('Audits.getEncodedResponse', params);
90
- }
91
-
92
- /**
93
- * @param {LH.Gatherer.ProtocolSession} session
94
- * @param {SimplifiedNetworkRecord} networkRecord
95
- * @return {Promise<{originalSize: number, jpegSize?: number, webpSize?: number}>}
96
- */
97
- async calculateImageStats(session, networkRecord) {
98
- const originalSize = networkRecord.resourceSize;
99
- // Once we've hit our execution time limit or when the image is too big, don't try to re-encode it.
100
- // Images in this execution path will fallback to byte-per-pixel heuristics on the audit side.
101
- if (Date.now() - this._encodingStartAt > MAX_TIME_TO_SPEND_ENCODING ||
102
- originalSize > MAX_RESOURCE_SIZE_TO_ENCODE) {
103
- return {originalSize, jpegSize: undefined, webpSize: undefined};
104
- }
105
-
106
- const jpegData = await this._getEncodedResponse(session, networkRecord.requestId, 'jpeg');
107
- const webpData = await this._getEncodedResponse(session, networkRecord.requestId, 'webp');
108
-
109
- return {
110
- originalSize,
111
- jpegSize: jpegData.encodedSize,
112
- webpSize: webpData.encodedSize,
113
- };
114
- }
115
-
116
- /**
117
- * @param {LH.Gatherer.ProtocolSession} session
118
- * @param {Array<SimplifiedNetworkRecord>} imageRecords
119
- * @return {Promise<LH.Artifacts['OptimizedImages']>}
120
- */
121
- async computeOptimizedImages(session, imageRecords) {
122
- this._encodingStartAt = Date.now();
123
-
124
- /** @type {LH.Artifacts['OptimizedImages']} */
125
- const results = [];
126
-
127
- for (const record of imageRecords) {
128
- try {
129
- const stats = await this.calculateImageStats(session, record);
130
- /** @type {LH.Artifacts.OptimizedImage} */
131
- const image = {failed: false, ...stats, ...record};
132
- results.push(image);
133
- } catch (err) {
134
- log.warn('optimized-images', err.message, record.url);
135
-
136
- // Track this with Sentry since these errors aren't surfaced anywhere else, but we don't
137
- // want to tank the entire run due to a single image.
138
- Sentry.captureException(err, {
139
- tags: {gatherer: 'OptimizedImages'},
140
- extra: {imageUrl: UrlUtils.elideDataURI(record.url)},
141
- level: 'warning',
142
- });
143
-
144
- /** @type {LH.Artifacts.OptimizedImageError} */
145
- const imageError = {failed: true, errMsg: err.message, ...record};
146
- results.push(imageError);
147
- }
148
- }
149
-
150
- return results;
151
- }
152
-
153
- /**
154
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} context
155
- * @return {Promise<LH.Artifacts['OptimizedImages']>}
156
- */
157
- async getArtifact(context) {
158
- const devtoolsLog = context.dependencies.DevtoolsLog;
159
- const networkRecords = await NetworkRecords.request(devtoolsLog, context);
160
-
161
- const imageRecords = OptimizedImages
162
- .filterImageRequests(networkRecords)
163
- .sort((a, b) => b.resourceSize - a.resourceSize);
164
-
165
- return await this.computeOptimizedImages(context.driver.defaultSession, imageRecords);
166
- }
167
- }
168
-
169
- export default OptimizedImages;
@@ -1,23 +0,0 @@
1
- export default ResponseCompression;
2
- declare class ResponseCompression extends BaseGatherer {
3
- /**
4
- * @param {LH.Artifacts.NetworkRequest[]} networkRecords
5
- * @return {LH.Artifacts['ResponseCompression']}
6
- */
7
- static filterUnoptimizedResponses(networkRecords: LH.Artifacts.NetworkRequest[]): LH.Artifacts["ResponseCompression"];
8
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
9
- meta: LH.Gatherer.GathererMeta<"DevtoolsLog">;
10
- /**
11
- * @param {LH.Gatherer.Context} context
12
- * @param {LH.Artifacts.NetworkRequest[]} networkRecords
13
- * @return {Promise<LH.Artifacts['ResponseCompression']>}
14
- */
15
- getCompressibleRecords(context: LH.Gatherer.Context, networkRecords: LH.Artifacts.NetworkRequest[]): Promise<LH.Artifacts["ResponseCompression"]>;
16
- /**
17
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} context
18
- * @return {Promise<LH.Artifacts['ResponseCompression']>}
19
- */
20
- getArtifact(context: LH.Gatherer.Context<"DevtoolsLog">): Promise<LH.Artifacts["ResponseCompression"]>;
21
- }
22
- import BaseGatherer from '../../base-gatherer.js';
23
- //# sourceMappingURL=response-compression.d.ts.map
@@ -1,136 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2017 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @fileoverview Determines optimized gzip/br/deflate filesizes for all responses by
9
- * checking the content-encoding header.
10
- */
11
-
12
-
13
- import {Buffer} from 'buffer';
14
- import {gzip} from 'zlib';
15
-
16
- import log from 'lighthouse-logger';
17
-
18
- import BaseGatherer from '../../base-gatherer.js';
19
- import UrlUtils from '../../../lib/url-utils.js';
20
- import {NetworkRequest} from '../../../lib/network-request.js';
21
- import DevtoolsLog from '../devtools-log.js';
22
- import {fetchResponseBodyFromCache} from '../../driver/network.js';
23
- import {NetworkRecords} from '../../../computed/network-records.js';
24
-
25
- const CHROME_EXTENSION_PROTOCOL = 'chrome-extension:';
26
- const binaryMimeTypes = ['image', 'audio', 'video'];
27
- /** @type {LH.Crdp.Network.ResourceType[]} */
28
- const textResourceTypes = [
29
- NetworkRequest.TYPES.Document,
30
- NetworkRequest.TYPES.Script,
31
- NetworkRequest.TYPES.Stylesheet,
32
- NetworkRequest.TYPES.XHR,
33
- NetworkRequest.TYPES.Fetch,
34
- NetworkRequest.TYPES.EventSource,
35
- ];
36
-
37
- class ResponseCompression extends BaseGatherer {
38
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
39
- meta = {
40
- supportedModes: ['timespan', 'navigation'],
41
- dependencies: {DevtoolsLog: DevtoolsLog.symbol},
42
- };
43
-
44
- /**
45
- * @param {LH.Artifacts.NetworkRequest[]} networkRecords
46
- * @return {LH.Artifacts['ResponseCompression']}
47
- */
48
- static filterUnoptimizedResponses(networkRecords) {
49
- /** @type {LH.Artifacts['ResponseCompression']} */
50
- const unoptimizedResponses = [];
51
-
52
- networkRecords.forEach(record => {
53
- if (record.sessionTargetType !== 'page') return;
54
-
55
- const mimeType = record.mimeType;
56
- const resourceType = record.resourceType || NetworkRequest.TYPES.Other;
57
- const resourceSize = record.resourceSize;
58
-
59
- const isBinaryResource = mimeType && binaryMimeTypes.some(type => mimeType.startsWith(type));
60
- const isTextResource = !isBinaryResource && textResourceTypes.includes(resourceType);
61
- const isChromeExtensionResource = record.url.startsWith(CHROME_EXTENSION_PROTOCOL);
62
-
63
- if (!isTextResource || !resourceSize || !record.finished ||
64
- isChromeExtensionResource || !record.transferSize || record.statusCode === 304) {
65
- return;
66
- }
67
-
68
- if (!NetworkRequest.isContentEncoded(record)) {
69
- unoptimizedResponses.push({
70
- requestId: record.requestId,
71
- url: record.url,
72
- mimeType: mimeType,
73
- transferSize: record.transferSize,
74
- resourceSize: resourceSize,
75
- gzipSize: 0,
76
- });
77
- }
78
- });
79
-
80
- return unoptimizedResponses;
81
- }
82
-
83
- /**
84
- * @param {LH.Gatherer.Context} context
85
- * @param {LH.Artifacts.NetworkRequest[]} networkRecords
86
- * @return {Promise<LH.Artifacts['ResponseCompression']>}
87
- */
88
- async getCompressibleRecords(context, networkRecords) {
89
- const session = context.driver.defaultSession;
90
- const textRecords = ResponseCompression.filterUnoptimizedResponses(networkRecords);
91
-
92
- return Promise.all(textRecords.map(record => {
93
- return fetchResponseBodyFromCache(session, record.requestId).then(content => {
94
- // if we don't have any content, gzipSize is already set to 0
95
- if (!content) {
96
- return record;
97
- }
98
-
99
- return new Promise((resolve, reject) => {
100
- return gzip(content, (err, res) => {
101
- if (err) {
102
- return reject(err);
103
- }
104
-
105
- // get gzip size
106
- record.gzipSize = Buffer.byteLength(res, 'utf8');
107
-
108
- resolve(record);
109
- });
110
- });
111
- }).catch(err => {
112
- const isExpectedError = err?.message?.includes('No resource with given identifier found');
113
- if (!isExpectedError) {
114
- err.extra = {url: UrlUtils.elideDataURI(record.url)};
115
- throw err;
116
- }
117
-
118
- log.error('ResponseCompression', err.message);
119
- record.gzipSize = undefined;
120
- return record;
121
- });
122
- }));
123
- }
124
-
125
- /**
126
- * @param {LH.Gatherer.Context<'DevtoolsLog'>} context
127
- * @return {Promise<LH.Artifacts['ResponseCompression']>}
128
- */
129
- async getArtifact(context) {
130
- const devtoolsLog = context.dependencies.DevtoolsLog;
131
- const networkRecords = await NetworkRecords.request(devtoolsLog, context);
132
- return this.getCompressibleRecords(context, networkRecords);
133
- }
134
- }
135
-
136
- export default ResponseCompression;