lighthouse 12.0.0-dev.20240529 → 12.0.0-dev.20240531
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.
|
@@ -4,12 +4,15 @@ export type PreparedAssets = {
|
|
|
4
4
|
};
|
|
5
5
|
/**
|
|
6
6
|
* Save artifacts object mostly to single file located at basePath/artifacts.json.
|
|
7
|
-
* Also save the traces & devtoolsLogs to their own files
|
|
7
|
+
* Also save the traces & devtoolsLogs to their own files, with optional compression.
|
|
8
8
|
* @param {LH.Artifacts} artifacts
|
|
9
9
|
* @param {string} basePath
|
|
10
|
+
* @param {{gzip?: boolean}} options
|
|
10
11
|
* @return {Promise<void>}
|
|
11
12
|
*/
|
|
12
|
-
export function saveArtifacts(artifacts: LH.Artifacts, basePath: string
|
|
13
|
+
export function saveArtifacts(artifacts: LH.Artifacts, basePath: string, options?: {
|
|
14
|
+
gzip?: boolean;
|
|
15
|
+
}): Promise<void>;
|
|
13
16
|
/**
|
|
14
17
|
* Saves flow artifacts with the following file structure:
|
|
15
18
|
* flow/ -- Directory specified by `basePath`.
|
|
@@ -32,11 +35,6 @@ export function saveFlowArtifacts(flowArtifacts: LH.UserFlow.FlowArtifacts, base
|
|
|
32
35
|
* @param {string} basePath
|
|
33
36
|
*/
|
|
34
37
|
export function saveLhr(lhr: LH.Result, basePath: string): void;
|
|
35
|
-
/**
|
|
36
|
-
* @typedef {object} PreparedAssets
|
|
37
|
-
* @property {LH.Trace} [traceData]
|
|
38
|
-
* @property {LH.DevtoolsLog} [devtoolsLog]
|
|
39
|
-
*/
|
|
40
38
|
/**
|
|
41
39
|
* Load artifacts object from files located within basePath
|
|
42
40
|
* Also save the traces to their own files
|
|
@@ -67,16 +65,22 @@ export function prepareAssets(artifacts: LH.Artifacts, audits?: Record<string, i
|
|
|
67
65
|
* Save a trace as JSON by streaming to disk at traceFilename.
|
|
68
66
|
* @param {LH.Trace} traceData
|
|
69
67
|
* @param {string} traceFilename
|
|
68
|
+
* @param {{gzip?: boolean}=} options
|
|
70
69
|
* @return {Promise<void>}
|
|
71
70
|
*/
|
|
72
|
-
export function saveTrace(traceData: LH.Trace, traceFilename: string
|
|
71
|
+
export function saveTrace(traceData: LH.Trace, traceFilename: string, options?: {
|
|
72
|
+
gzip?: boolean;
|
|
73
|
+
} | undefined): Promise<void>;
|
|
73
74
|
/**
|
|
74
75
|
* Save a devtoolsLog as JSON by streaming to disk at devtoolLogFilename.
|
|
75
76
|
* @param {LH.DevtoolsLog} devtoolsLog
|
|
76
77
|
* @param {string} devtoolLogFilename
|
|
78
|
+
* @param {{gzip?: boolean}=} options
|
|
77
79
|
* @return {Promise<void>}
|
|
78
80
|
*/
|
|
79
|
-
export function saveDevtoolsLog(devtoolsLog: import("../index.js").DevtoolsLog, devtoolLogFilename: string
|
|
81
|
+
export function saveDevtoolsLog(devtoolsLog: import("../index.js").DevtoolsLog, devtoolLogFilename: string, options?: {
|
|
82
|
+
gzip?: boolean;
|
|
83
|
+
} | undefined): Promise<void>;
|
|
80
84
|
/**
|
|
81
85
|
* @param {LH.DevtoolsLog} devtoolsLog
|
|
82
86
|
* @param {string} outputPath
|
package/core/lib/asset-saver.js
CHANGED
|
@@ -8,6 +8,7 @@ import fs from 'fs';
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import stream from 'stream';
|
|
10
10
|
import url from 'url';
|
|
11
|
+
import {createGzip, gunzipSync} from 'zlib';
|
|
11
12
|
|
|
12
13
|
import log from 'lighthouse-logger';
|
|
13
14
|
|
|
@@ -33,6 +34,46 @@ const stepDirectoryRegex = /^step(\d+)$/;
|
|
|
33
34
|
* @property {LH.DevtoolsLog} [devtoolsLog]
|
|
34
35
|
*/
|
|
35
36
|
|
|
37
|
+
/**
|
|
38
|
+
* @param {import('stream').PipelineSource<any>} contents
|
|
39
|
+
* @param {string} path
|
|
40
|
+
* @param {boolean} gzip
|
|
41
|
+
*/
|
|
42
|
+
async function writeJson(contents, path, gzip) {
|
|
43
|
+
const writeStream = fs.createWriteStream(gzip ? path + '.gz' : path);
|
|
44
|
+
if (gzip) {
|
|
45
|
+
await stream.promises.pipeline(contents, createGzip(), writeStream);
|
|
46
|
+
} else {
|
|
47
|
+
await stream.promises.pipeline(contents, writeStream);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Prefers reading a gzipped file (.gz) if present.
|
|
53
|
+
* @param {string} filename
|
|
54
|
+
* @param {(this: any, key: string, value: any) => any=} reviver
|
|
55
|
+
*/
|
|
56
|
+
function readJson(filename, reviver) {
|
|
57
|
+
if (fs.existsSync(filename + '.gz')) {
|
|
58
|
+
filename = filename + '.gz';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!filename.endsWith('.json.gz')) {
|
|
62
|
+
return JSON.parse(fs.readFileSync(filename, 'utf8'), reviver);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const buffer = gunzipSync(fs.readFileSync(filename));
|
|
66
|
+
return JSON.parse(buffer.toString('utf8'), reviver);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} filename
|
|
71
|
+
* @param {string} suffix
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
function endsWithSuffix(filename, suffix) {
|
|
75
|
+
return filename.endsWith(suffix) || filename.endsWith(suffix + '.gz');
|
|
76
|
+
}
|
|
36
77
|
|
|
37
78
|
/**
|
|
38
79
|
* Load artifacts object from files located within basePath
|
|
@@ -48,16 +89,15 @@ function loadArtifacts(basePath) {
|
|
|
48
89
|
}
|
|
49
90
|
|
|
50
91
|
// load artifacts.json using a reviver to deserialize any LighthouseErrors in artifacts.
|
|
51
|
-
const artifactsStr = fs.readFileSync(path.join(basePath, artifactsFilename), 'utf8');
|
|
52
92
|
/** @type {LH.Artifacts} */
|
|
53
|
-
const artifacts =
|
|
93
|
+
const artifacts = readJson(path.join(basePath, artifactsFilename), LighthouseError.parseReviver);
|
|
54
94
|
|
|
55
95
|
const filenames = fs.readdirSync(basePath);
|
|
56
96
|
|
|
57
|
-
filenames.filter(f => f
|
|
97
|
+
filenames.filter(f => endsWithSuffix(f, devtoolsLogSuffix)).forEach(filename => {
|
|
58
98
|
if (!artifacts.devtoolsLogs) artifacts.devtoolsLogs = {};
|
|
59
|
-
const prefix = filename.replace(devtoolsLogSuffix, '');
|
|
60
|
-
const devtoolsLog =
|
|
99
|
+
const prefix = filename.replace(devtoolsLogSuffix + '.gz', '').replace(devtoolsLogSuffix, '');
|
|
100
|
+
const devtoolsLog = readJson(path.join(basePath, filename));
|
|
61
101
|
artifacts.devtoolsLogs[prefix] = devtoolsLog;
|
|
62
102
|
if (prefix === defaultPrefix) {
|
|
63
103
|
artifacts.DevtoolsLog = devtoolsLog;
|
|
@@ -67,11 +107,10 @@ function loadArtifacts(basePath) {
|
|
|
67
107
|
}
|
|
68
108
|
});
|
|
69
109
|
|
|
70
|
-
filenames.filter(f => f
|
|
110
|
+
filenames.filter(f => endsWithSuffix(f, traceSuffix)).forEach(filename => {
|
|
71
111
|
if (!artifacts.traces) artifacts.traces = {};
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const prefix = filename.replace(traceSuffix, '');
|
|
112
|
+
const trace = readJson(path.join(basePath, filename));
|
|
113
|
+
const prefix = filename.replace(traceSuffix + '.gz', '').replace(traceSuffix, '');
|
|
75
114
|
artifacts.traces[prefix] = Array.isArray(trace) ? {traceEvents: trace} : trace;
|
|
76
115
|
if (prefix === defaultPrefix) {
|
|
77
116
|
artifacts.Trace = artifacts.traces[prefix];
|
|
@@ -200,12 +239,13 @@ async function saveFlowArtifacts(flowArtifacts, basePath) {
|
|
|
200
239
|
|
|
201
240
|
/**
|
|
202
241
|
* Save artifacts object mostly to single file located at basePath/artifacts.json.
|
|
203
|
-
* Also save the traces & devtoolsLogs to their own files
|
|
242
|
+
* Also save the traces & devtoolsLogs to their own files, with optional compression.
|
|
204
243
|
* @param {LH.Artifacts} artifacts
|
|
205
244
|
* @param {string} basePath
|
|
245
|
+
* @param {{gzip?: boolean}} options
|
|
206
246
|
* @return {Promise<void>}
|
|
207
247
|
*/
|
|
208
|
-
async function saveArtifacts(artifacts, basePath) {
|
|
248
|
+
async function saveArtifacts(artifacts, basePath, options = {}) {
|
|
209
249
|
const status = {msg: 'Saving artifacts', id: 'lh:assetSaver:saveArtifacts'};
|
|
210
250
|
log.time(status);
|
|
211
251
|
fs.mkdirSync(basePath, {recursive: true});
|
|
@@ -213,8 +253,11 @@ async function saveArtifacts(artifacts, basePath) {
|
|
|
213
253
|
// Delete any previous artifacts in this directory.
|
|
214
254
|
const filenames = fs.readdirSync(basePath);
|
|
215
255
|
for (const filename of filenames) {
|
|
216
|
-
|
|
217
|
-
|
|
256
|
+
const isPreviousFile =
|
|
257
|
+
filename.endsWith(traceSuffix) || filename.endsWith(devtoolsLogSuffix) ||
|
|
258
|
+
filename.endsWith(traceSuffix + '.gz') || filename.endsWith(devtoolsLogSuffix + '.gz') ||
|
|
259
|
+
filename === artifactsFilename || filename === artifactsFilename + '.gz';
|
|
260
|
+
if (isPreviousFile) {
|
|
218
261
|
fs.unlinkSync(`${basePath}/${filename}`);
|
|
219
262
|
}
|
|
220
263
|
}
|
|
@@ -234,24 +277,30 @@ async function saveArtifacts(artifacts, basePath) {
|
|
|
234
277
|
} = artifacts;
|
|
235
278
|
|
|
236
279
|
if (Trace) {
|
|
237
|
-
await saveTrace(Trace, `${basePath}/${defaultPrefix}${traceSuffix}
|
|
280
|
+
await saveTrace(Trace, `${basePath}/${defaultPrefix}${traceSuffix}`, options);
|
|
238
281
|
}
|
|
239
282
|
|
|
240
283
|
if (TraceError) {
|
|
241
|
-
await saveTrace(TraceError, `${basePath}/${errorPrefix}${traceSuffix}
|
|
284
|
+
await saveTrace(TraceError, `${basePath}/${errorPrefix}${traceSuffix}`, options);
|
|
242
285
|
}
|
|
243
286
|
|
|
244
287
|
if (DevtoolsLog) {
|
|
245
|
-
await saveDevtoolsLog(
|
|
288
|
+
await saveDevtoolsLog(
|
|
289
|
+
DevtoolsLog, `${basePath}/${defaultPrefix}${devtoolsLogSuffix}`, options);
|
|
246
290
|
}
|
|
247
291
|
|
|
248
292
|
if (DevtoolsLogError) {
|
|
249
|
-
await saveDevtoolsLog(
|
|
293
|
+
await saveDevtoolsLog(
|
|
294
|
+
DevtoolsLogError, `${basePath}/${errorPrefix}${devtoolsLogSuffix}`, options);
|
|
250
295
|
}
|
|
251
296
|
|
|
252
297
|
// save everything else, using a replacer to serialize LighthouseErrors in the artifacts.
|
|
253
|
-
const restArtifactsString = JSON.stringify(restArtifacts, stringifyReplacer, 2)
|
|
254
|
-
|
|
298
|
+
const restArtifactsString = JSON.stringify(restArtifacts, stringifyReplacer, 2);
|
|
299
|
+
await writeJson(function* () {
|
|
300
|
+
yield restArtifactsString;
|
|
301
|
+
yield '\n';
|
|
302
|
+
}, `${basePath}/${artifactsFilename}`, !!options.gzip);
|
|
303
|
+
|
|
255
304
|
log.log('Artifacts saved to disk in folder:', basePath);
|
|
256
305
|
log.timeEnd(status);
|
|
257
306
|
}
|
|
@@ -371,28 +420,26 @@ function* traceJsonGenerator(traceData) {
|
|
|
371
420
|
* Save a trace as JSON by streaming to disk at traceFilename.
|
|
372
421
|
* @param {LH.Trace} traceData
|
|
373
422
|
* @param {string} traceFilename
|
|
423
|
+
* @param {{gzip?: boolean}=} options
|
|
374
424
|
* @return {Promise<void>}
|
|
375
425
|
*/
|
|
376
|
-
|
|
426
|
+
function saveTrace(traceData, traceFilename, options = {}) {
|
|
377
427
|
const traceIter = traceJsonGenerator(traceData);
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return stream.promises.pipeline(traceIter, writeStream);
|
|
428
|
+
return writeJson(traceIter, traceFilename, !!options.gzip);
|
|
381
429
|
}
|
|
382
430
|
|
|
383
431
|
/**
|
|
384
432
|
* Save a devtoolsLog as JSON by streaming to disk at devtoolLogFilename.
|
|
385
433
|
* @param {LH.DevtoolsLog} devtoolsLog
|
|
386
434
|
* @param {string} devtoolLogFilename
|
|
435
|
+
* @param {{gzip?: boolean}=} options
|
|
387
436
|
* @return {Promise<void>}
|
|
388
437
|
*/
|
|
389
|
-
function saveDevtoolsLog(devtoolsLog, devtoolLogFilename) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
return stream.promises.pipeline(function* () {
|
|
438
|
+
function saveDevtoolsLog(devtoolsLog, devtoolLogFilename, options = {}) {
|
|
439
|
+
return writeJson(function* () {
|
|
393
440
|
yield* arrayOfObjectsJsonGenerator(devtoolsLog);
|
|
394
441
|
yield '\n';
|
|
395
|
-
},
|
|
442
|
+
}, devtoolLogFilename, !!options.gzip);
|
|
396
443
|
}
|
|
397
444
|
|
|
398
445
|
/**
|
|
@@ -380,7 +380,7 @@ const UIStrings = {
|
|
|
380
380
|
/**
|
|
381
381
|
* @description Description text for not restored reason NotMainFrame.
|
|
382
382
|
*/
|
|
383
|
-
contentWebAuthenticationAPI: 'Pages that use
|
|
383
|
+
contentWebAuthenticationAPI: 'Pages that use WebAuthentication API are not eligible for back/forward cache.',
|
|
384
384
|
/**
|
|
385
385
|
* @description Description text for not restored reason NotMainFrame.
|
|
386
386
|
*/
|
|
@@ -674,4 +674,4 @@ const NotRestoredReasonDescription = {
|
|
|
674
674
|
export {
|
|
675
675
|
NotRestoredReasonDescription,
|
|
676
676
|
UIStrings,
|
|
677
|
-
};
|
|
677
|
+
};
|
package/package.json
CHANGED
|
@@ -1740,7 +1740,7 @@
|
|
|
1740
1740
|
"message": "Pages that use Serial API are not eligible for back/forward cache."
|
|
1741
1741
|
},
|
|
1742
1742
|
"core/lib/bf-cache-strings.js | contentWebAuthenticationAPI": {
|
|
1743
|
-
"message": "Pages that use
|
|
1743
|
+
"message": "Pages that use WebAuthentication API are not eligible for back/forward cache."
|
|
1744
1744
|
},
|
|
1745
1745
|
"core/lib/bf-cache-strings.js | contentWebBluetooth": {
|
|
1746
1746
|
"message": "Pages that use WebBluetooth API are not eligible for back/forward cache."
|
|
@@ -1740,7 +1740,7 @@
|
|
|
1740
1740
|
"message": "P̂áĝéŝ t́ĥát̂ úŝé Ŝér̂íâĺ ÂṔÎ ár̂é n̂ót̂ él̂íĝíb̂ĺê f́ôŕ b̂áĉḱ/f̂ór̂ẃâŕd̂ ćâćĥé."
|
|
1741
1741
|
},
|
|
1742
1742
|
"core/lib/bf-cache-strings.js | contentWebAuthenticationAPI": {
|
|
1743
|
-
"message": "P̂áĝéŝ t́ĥát̂ úŝé Ŵéb̂Áût́ĥét̂
|
|
1743
|
+
"message": "P̂áĝéŝ t́ĥát̂ úŝé Ŵéb̂Áût́ĥén̂t́îćât́îón̂ ÁP̂Í âŕê ńôt́ êĺîǵîb́l̂é f̂ór̂ b́âćk̂/f́ôŕŵár̂d́ ĉáĉh́ê."
|
|
1744
1744
|
},
|
|
1745
1745
|
"core/lib/bf-cache-strings.js | contentWebBluetooth": {
|
|
1746
1746
|
"message": "P̂áĝéŝ t́ĥát̂ úŝé Ŵéb̂B́l̂úêt́ôót̂h́ ÂṔÎ ár̂é n̂ót̂ él̂íĝíb̂ĺê f́ôŕ b̂áĉḱ/f̂ór̂ẃâŕd̂ ćâćĥé."
|