lighthouse 11.3.0-dev.20231205 → 11.3.0-dev.20231207

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 (36) hide show
  1. package/core/audits/bf-cache.d.ts +1 -0
  2. package/core/audits/bf-cache.js +11 -1
  3. package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +0 -24
  4. package/core/audits/byte-efficiency/byte-efficiency-audit.js +0 -102
  5. package/core/audits/byte-efficiency/duplicated-javascript.d.ts +0 -6
  6. package/core/audits/byte-efficiency/duplicated-javascript.js +9 -38
  7. package/core/audits/byte-efficiency/legacy-javascript.d.ts +0 -13
  8. package/core/audits/byte-efficiency/legacy-javascript.js +2 -36
  9. package/core/audits/byte-efficiency/unminified-css.js +2 -2
  10. package/core/audits/byte-efficiency/unminified-javascript.js +2 -3
  11. package/core/audits/byte-efficiency/unused-javascript.js +10 -11
  12. package/core/audits/resource-summary.d.ts +11 -0
  13. package/core/audits/resource-summary.js +86 -0
  14. package/core/computed/unused-css.js +2 -2
  15. package/core/config/default-config.js +2 -0
  16. package/core/config/filters.js +1 -0
  17. package/core/gather/base-artifacts.js +2 -1
  18. package/core/lib/i18n/i18n.d.ts +2 -2
  19. package/core/lib/i18n/i18n.js +2 -2
  20. package/core/lib/network-request.js +4 -1
  21. package/core/lib/script-helpers.d.ts +34 -5
  22. package/core/lib/script-helpers.js +136 -0
  23. package/dist/report/bundle.esm.js +24 -9
  24. package/dist/report/flow.js +25 -10
  25. package/dist/report/standalone.js +25 -10
  26. package/package.json +1 -1
  27. package/report/assets/styles.css +20 -5
  28. package/report/assets/templates.html +1 -1
  29. package/report/clients/standalone.js +1 -0
  30. package/report/renderer/components.js +2 -2
  31. package/report/renderer/report-renderer.js +4 -0
  32. package/report/types/report-renderer.d.ts +2 -0
  33. package/shared/localization/locales/en-US.json +3 -0
  34. package/shared/localization/locales/en-XL.json +3 -0
  35. package/tsconfig.json +1 -0
  36. package/types/artifacts.d.ts +2 -0
@@ -614,7 +614,10 @@ class NetworkRequest {
614
614
  * @return {boolean}
615
615
  */
616
616
  static isContentEncoded(record) {
617
- return record.responseHeaders.some(item => item.name === 'Content-Encoding');
617
+ // FYI: older devtools logs (like our test fixtures) seems to be lower case, while modern logs
618
+ // are Cased-Like-This.
619
+ const pattern = /^content-encoding$/i;
620
+ return record.responseHeaders.some(item => item.name.match(pattern));
618
621
  }
619
622
 
620
623
  /**
@@ -4,14 +4,43 @@
4
4
  * @return {LH.Artifacts.NetworkRequest|undefined}
5
5
  */
6
6
  export function getRequestForScript(networkRecords: LH.Artifacts.NetworkRequest[], script: LH.Artifacts.Script): LH.Artifacts.NetworkRequest | undefined;
7
- /**
8
- * @license
9
- * Copyright 2022 Google LLC
10
- * SPDX-License-Identifier: Apache-2.0
11
- */
12
7
  /**
13
8
  * @param {LH.Artifacts.Script} script
14
9
  * @return {boolean}
15
10
  */
16
11
  export function isInline(script: LH.Artifacts.Script): boolean;
12
+ /**
13
+ * Estimates the number of bytes the content of this network record would have consumed on the network based on the
14
+ * uncompressed size (totalBytes). Uses the actual transfer size from the network record if applicable,
15
+ * minus the size of the response headers.
16
+ *
17
+ * This differs from `estimateTransferSize` only in that is subtracts the response headers from the estimate.
18
+ *
19
+ * @param {LH.Artifacts.NetworkRequest|undefined} networkRecord
20
+ * @param {number} totalBytes Uncompressed size of the resource
21
+ * @param {LH.Crdp.Network.ResourceType=} resourceType
22
+ * @return {number}
23
+ */
24
+ export function estimateCompressedContentSize(networkRecord: LH.Artifacts.NetworkRequest | undefined, totalBytes: number, resourceType?: LH.Crdp.Network.ResourceType | undefined): number;
25
+ /**
26
+ * Estimates the number of bytes this network record would have consumed on the network based on the
27
+ * uncompressed size (totalBytes). Uses the actual transfer size from the network record if applicable.
28
+ *
29
+ * @param {LH.Artifacts.NetworkRequest|undefined} networkRecord
30
+ * @param {number} totalBytes Uncompressed size of the resource
31
+ * @param {LH.Crdp.Network.ResourceType=} resourceType
32
+ * @return {number}
33
+ */
34
+ export function estimateTransferSize(networkRecord: LH.Artifacts.NetworkRequest | undefined, totalBytes: number, resourceType?: LH.Crdp.Network.ResourceType | undefined): number;
35
+ /**
36
+ * Utility function to estimate the ratio of the compression on the resource.
37
+ * This excludes the size of the response headers.
38
+ * Also caches the calculation.
39
+ * @param {Map<string, number>} compressionRatioByUrl
40
+ * @param {string} url
41
+ * @param {LH.Artifacts} artifacts
42
+ * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
43
+ */
44
+ export function estimateCompressionRatioForContent(compressionRatioByUrl: Map<string, number>, url: string, artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>): number;
45
+ import { NetworkRequest } from './network-request.js';
17
46
  //# sourceMappingURL=script-helpers.d.ts.map
@@ -4,6 +4,8 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import {NetworkRequest} from './network-request.js';
8
+
7
9
  /**
8
10
  * @param {LH.Artifacts.Script} script
9
11
  * @return {boolean}
@@ -25,7 +27,141 @@ function getRequestForScript(networkRecords, script) {
25
27
  return networkRequest;
26
28
  }
27
29
 
30
+ /**
31
+ * Estimates the number of bytes this network record would have consumed on the network based on the
32
+ * uncompressed size (totalBytes). Uses the actual transfer size from the network record if applicable.
33
+ *
34
+ * @param {LH.Artifacts.NetworkRequest|undefined} networkRecord
35
+ * @param {number} totalBytes Uncompressed size of the resource
36
+ * @param {LH.Crdp.Network.ResourceType=} resourceType
37
+ * @return {number}
38
+ */
39
+ function estimateTransferSize(networkRecord, totalBytes, resourceType) {
40
+ if (!networkRecord) {
41
+ // We don't know how many bytes this asset used on the network, but we can guess it was
42
+ // roughly the size of the content gzipped.
43
+ // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples
44
+ // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers
45
+ switch (resourceType) {
46
+ case 'Stylesheet':
47
+ // Stylesheets tend to compress extremely well.
48
+ return Math.round(totalBytes * 0.2);
49
+ case 'Script':
50
+ case 'Document':
51
+ // Scripts and HTML compress fairly well too.
52
+ return Math.round(totalBytes * 0.33);
53
+ default:
54
+ // Otherwise we'll just fallback to the average savings in HTTPArchive
55
+ return Math.round(totalBytes * 0.5);
56
+ }
57
+ } else if (networkRecord.resourceType === resourceType) {
58
+ // This was a regular standalone asset, just use the transfer size.
59
+ return networkRecord.transferSize || 0;
60
+ } else {
61
+ // This was an asset that was inlined in a different resource type (e.g. HTML document).
62
+ // Use the compression ratio of the resource to estimate the total transferred bytes.
63
+ const transferSize = networkRecord.transferSize || 0;
64
+ const resourceSize = networkRecord.resourceSize || 0;
65
+ // Get the compression ratio, if it's an invalid number, assume no compression.
66
+ const compressionRatio = Number.isFinite(resourceSize) && resourceSize > 0 ?
67
+ (transferSize / resourceSize) : 1;
68
+ return Math.round(totalBytes * compressionRatio);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Estimates the number of bytes the content of this network record would have consumed on the network based on the
74
+ * uncompressed size (totalBytes). Uses the actual transfer size from the network record if applicable,
75
+ * minus the size of the response headers.
76
+ *
77
+ * This differs from `estimateTransferSize` only in that is subtracts the response headers from the estimate.
78
+ *
79
+ * @param {LH.Artifacts.NetworkRequest|undefined} networkRecord
80
+ * @param {number} totalBytes Uncompressed size of the resource
81
+ * @param {LH.Crdp.Network.ResourceType=} resourceType
82
+ * @return {number}
83
+ */
84
+ function estimateCompressedContentSize(networkRecord, totalBytes, resourceType) {
85
+ if (!networkRecord) {
86
+ // We don't know how many bytes this asset used on the network, but we can guess it was
87
+ // roughly the size of the content gzipped.
88
+ // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples
89
+ // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers
90
+ switch (resourceType) {
91
+ case 'Stylesheet':
92
+ // Stylesheets tend to compress extremely well.
93
+ return Math.round(totalBytes * 0.2);
94
+ case 'Script':
95
+ case 'Document':
96
+ // Scripts and HTML compress fairly well too.
97
+ return Math.round(totalBytes * 0.33);
98
+ default:
99
+ // Otherwise we'll just fallback to the average savings in HTTPArchive
100
+ return Math.round(totalBytes * 0.5);
101
+ }
102
+ }
103
+
104
+ // Get the size of the response body on the network.
105
+ let contentTransferSize = networkRecord.transferSize || 0;
106
+ if (!NetworkRequest.isContentEncoded(networkRecord)) {
107
+ // This is not encoded, so we can use resourceSize directly.
108
+ // This would be equivalent to transfer size minus headers transfer size, but transfer size
109
+ // may also include bytes for SSL connection etc.
110
+ contentTransferSize = networkRecord.resourceSize;
111
+ } else if (networkRecord.responseHeadersTransferSize) {
112
+ // Subtract the size of the encoded headers.
113
+ contentTransferSize =
114
+ Math.max(0, contentTransferSize - networkRecord.responseHeadersTransferSize);
115
+ }
116
+
117
+ if (networkRecord.resourceType === resourceType) {
118
+ // This was a regular standalone asset, just use the transfer size.
119
+ return contentTransferSize;
120
+ } else {
121
+ // This was an asset that was inlined in a different resource type (e.g. HTML document).
122
+ // Use the compression ratio of the resource to estimate the total transferred bytes.
123
+ const resourceSize = networkRecord.resourceSize || 0;
124
+ // Get the compression ratio, if it's an invalid number, assume no compression.
125
+ const compressionRatio = Number.isFinite(resourceSize) && resourceSize > 0 ?
126
+ (contentTransferSize / resourceSize) : 1;
127
+ return Math.round(totalBytes * compressionRatio);
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Utility function to estimate the ratio of the compression on the resource.
133
+ * This excludes the size of the response headers.
134
+ * Also caches the calculation.
135
+ * @param {Map<string, number>} compressionRatioByUrl
136
+ * @param {string} url
137
+ * @param {LH.Artifacts} artifacts
138
+ * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
139
+ */
140
+ function estimateCompressionRatioForContent(compressionRatioByUrl, url,
141
+ artifacts, networkRecords) {
142
+ let compressionRatio = compressionRatioByUrl.get(url);
143
+ if (compressionRatio !== undefined) return compressionRatio;
144
+
145
+ const script = artifacts.Scripts.find(script => script.url === url);
146
+
147
+ if (!script) {
148
+ // Can't find content, so just use 1.
149
+ compressionRatio = 1;
150
+ } else {
151
+ const networkRecord = getRequestForScript(networkRecords, script);
152
+ const contentLength = networkRecord?.resourceSize || script.length || 0;
153
+ const compressedSize = estimateCompressedContentSize(networkRecord, contentLength, 'Script');
154
+ compressionRatio = compressedSize / contentLength;
155
+ }
156
+
157
+ compressionRatioByUrl.set(url, compressionRatio);
158
+ return compressionRatio;
159
+ }
160
+
28
161
  export {
29
162
  getRequestForScript,
30
163
  isInline,
164
+ estimateCompressedContentSize,
165
+ estimateTransferSize,
166
+ estimateCompressionRatioForContent,
31
167
  };