lighthouse 9.5.0-dev.20220329 → 9.5.0-dev.20220401

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 (69) hide show
  1. package/dist/report/bundle.esm.js +20 -18
  2. package/dist/report/flow.js +1 -1
  3. package/dist/report/standalone.js +1 -1
  4. package/lighthouse-cli/test/smokehouse/lighthouse-runners/devtools.js +28 -18
  5. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +2 -1
  6. package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  7. package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +3 -2
  8. package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +1 -1
  9. package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -1
  10. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +1 -1
  11. package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
  12. package/lighthouse-core/audits/dobetterweb/uses-http2.js +2 -1
  13. package/lighthouse-core/audits/long-tasks.js +3 -2
  14. package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -2
  15. package/lighthouse-core/audits/metrics/first-contentful-paint.js +3 -2
  16. package/lighthouse-core/audits/metrics/first-meaningful-paint.js +3 -2
  17. package/lighthouse-core/audits/metrics/interactive.js +3 -2
  18. package/lighthouse-core/audits/metrics/largest-contentful-paint.js +3 -2
  19. package/lighthouse-core/audits/metrics/max-potential-fid.js +3 -2
  20. package/lighthouse-core/audits/metrics/speed-index.js +3 -2
  21. package/lighthouse-core/audits/metrics/total-blocking-time.js +3 -2
  22. package/lighthouse-core/audits/metrics.js +3 -2
  23. package/lighthouse-core/audits/predictive-perf.js +2 -1
  24. package/lighthouse-core/audits/preload-lcp-image.js +3 -3
  25. package/lighthouse-core/audits/redirects.js +1 -1
  26. package/lighthouse-core/audits/script-treemap-data.js +31 -32
  27. package/lighthouse-core/audits/timing-budget.js +3 -2
  28. package/lighthouse-core/audits/uses-rel-preconnect.js +1 -1
  29. package/lighthouse-core/audits/uses-rel-preload.js +1 -1
  30. package/lighthouse-core/computed/critical-request-chains.js +2 -9
  31. package/lighthouse-core/computed/main-resource.js +1 -1
  32. package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
  33. package/lighthouse-core/computed/metrics/first-contentful-paint.js +1 -1
  34. package/lighthouse-core/computed/metrics/first-meaningful-paint.js +1 -1
  35. package/lighthouse-core/computed/metrics/interactive.js +1 -1
  36. package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +1 -1
  37. package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +1 -1
  38. package/lighthouse-core/computed/metrics/lantern-interactive.js +1 -1
  39. package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
  40. package/lighthouse-core/computed/metrics/lantern-max-potential-fid.js +1 -1
  41. package/lighthouse-core/computed/metrics/lantern-metric.js +3 -5
  42. package/lighthouse-core/computed/metrics/lantern-speed-index.js +1 -1
  43. package/lighthouse-core/computed/metrics/lantern-total-blocking-time.js +1 -1
  44. package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
  45. package/lighthouse-core/computed/metrics/largest-contentful-paint.js +1 -1
  46. package/lighthouse-core/computed/metrics/max-potential-fid.js +1 -1
  47. package/lighthouse-core/computed/metrics/metric.js +1 -0
  48. package/lighthouse-core/computed/metrics/speed-index.js +1 -1
  49. package/lighthouse-core/computed/metrics/timing-summary.js +13 -6
  50. package/lighthouse-core/computed/metrics/total-blocking-time.js +1 -1
  51. package/lighthouse-core/computed/page-dependency-graph.js +54 -31
  52. package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +0 -3
  53. package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +0 -1
  54. package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +0 -2
  55. package/lighthouse-core/gather/connections/cri.js +1 -0
  56. package/lighthouse-core/gather/driver/execution-context.js +4 -2
  57. package/lighthouse-core/gather/gatherers/js-usage.js +7 -6
  58. package/lighthouse-core/gather/gatherers/scripts.js +20 -2
  59. package/lighthouse-core/gather/gatherers/seo/robots-txt.js +2 -1
  60. package/lighthouse-core/gather/gatherers/web-app-manifest.js +2 -2
  61. package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +8 -29
  62. package/lighthouse-core/lib/navigation-error.js +13 -4
  63. package/lighthouse-core/util-commonjs.js +20 -18
  64. package/package.json +4 -4
  65. package/report/renderer/util.js +20 -18
  66. package/shared/localization/locales/en-US.json +1 -1
  67. package/shared/localization/locales/en-XL.json +1 -1
  68. package/types/artifacts.d.ts +1 -0
  69. package/types/gatherer.d.ts +0 -2
@@ -8,13 +8,14 @@
8
8
  const makeComputedArtifact = require('./computed-artifact.js');
9
9
  const NetworkNode = require('../lib/dependency-graph/network-node.js');
10
10
  const CPUNode = require('../lib/dependency-graph/cpu-node.js');
11
- const NetworkAnalyzer = require('../lib/dependency-graph/simulator/network-analyzer.js');
12
11
  const TracingProcessor = require('../lib/tracehouse/trace-processor.js');
13
12
  const NetworkRequest = require('../lib/network-request.js');
14
13
  const ProcessedTrace = require('./processed-trace.js');
15
14
  const NetworkRecords = require('./network-records.js');
15
+ const NetworkAnalyzer = require('../lib/dependency-graph/simulator/network-analyzer.js');
16
16
 
17
17
  /** @typedef {import('../lib/dependency-graph/base-node.js').Node} Node */
18
+ /** @typedef {Omit<LH.Artifacts['URL'], 'initialUrl'|'finalUrl'>} URLArtifact */
18
19
 
19
20
  // Shorter tasks have negligible impact on simulation results.
20
21
  const SIGNIFICANT_DUR_THRESHOLD_MS = 10;
@@ -388,37 +389,24 @@ class PageDependencyGraph {
388
389
  /**
389
390
  * @param {LH.Artifacts.ProcessedTrace} processedTrace
390
391
  * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
392
+ * @param {URLArtifact} URL
391
393
  * @return {Node}
392
394
  */
393
- static createGraph(processedTrace, networkRecords) {
395
+ static createGraph(processedTrace, networkRecords, URL) {
394
396
  const networkNodeOutput = PageDependencyGraph.getNetworkNodeOutput(networkRecords);
395
397
  const cpuNodes = PageDependencyGraph.getCPUNodes(processedTrace);
398
+ const {requestedUrl, mainDocumentUrl} = URL;
399
+ if (!mainDocumentUrl) throw new Error('mainDocumentUrl is required to get the main resource');
396
400
 
397
- // TODO: Remove this usage of `findMainDocument` and create a new function to get the first document request.
398
- // https://github.com/GoogleChrome/lighthouse/issues/8984
399
- //
400
- // The main document request is the earliest network request *of type document*.
401
- // This will be different from the root request when there are server redirects.
402
- const mainDocumentRequest = NetworkAnalyzer.findMainDocument(networkRecords);
403
- const mainDocumentNode = networkNodeOutput.idToNodeMap.get(mainDocumentRequest.requestId);
404
- if (!mainDocumentNode) {
405
- // mainDocumentNode should always be found.
406
- throw new Error('mainDocumentNode not found.');
407
- }
401
+ const rootRequest = NetworkAnalyzer.findResourceForUrl(networkRecords, requestedUrl);
402
+ if (!rootRequest) throw new Error('rootRequest not found');
403
+ const rootNode = networkNodeOutput.idToNodeMap.get(rootRequest.requestId);
404
+ if (!rootNode) throw new Error('rootNode not found');
408
405
 
409
- // The root request is the earliest request in the main document redirect chain.
410
- // Will be undefined if there were no redirects.
411
- const rootRequest = mainDocumentNode.record.redirects?.[0];
412
-
413
- let rootNode;
414
- if (rootRequest) {
415
- // rootNode should always be found.
416
- rootNode = rootRequest && networkNodeOutput.idToNodeMap.get(rootRequest.requestId);
417
- if (!rootNode) throw new Error('rootNode not found');
418
- } else {
419
- // Use main document as root if there were no redirects.
420
- rootNode = mainDocumentNode;
421
- }
406
+ const mainDocumentRequest = NetworkAnalyzer.findResourceForUrl(networkRecords, mainDocumentUrl);
407
+ if (!mainDocumentRequest) throw new Error('mainDocumentRequest not found');
408
+ const mainDocumentNode = networkNodeOutput.idToNodeMap.get(mainDocumentRequest.requestId);
409
+ if (!mainDocumentNode) throw new Error('mainDocumentNode not found');
422
410
 
423
411
  PageDependencyGraph.linkNetworkNodes(rootNode, networkNodeOutput);
424
412
  PageDependencyGraph.linkCPUNodes(rootNode, networkNodeOutput, cpuNodes);
@@ -464,23 +452,58 @@ class PageDependencyGraph {
464
452
  }
465
453
 
466
454
  /**
467
- * @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog}} data
455
+ * Recalculate `artifacts.URL` for clients that don't provide it.
456
+ *
457
+ * @param {LH.DevtoolsLog} devtoolsLog
458
+ * @param {LH.Artifacts.NetworkRequest[]} networkRecords
459
+ * @param {LH.Artifacts.ProcessedTrace} processedTrace
460
+ * @return {URLArtifact}
461
+ */
462
+ static getDocumentUrls(devtoolsLog, networkRecords, processedTrace) {
463
+ const mainFrameId = processedTrace.mainFrameIds.frameId;
464
+
465
+ /** @type {string|undefined} */
466
+ let requestedUrl;
467
+ /** @type {string|undefined} */
468
+ let mainDocumentUrl;
469
+ for (const event of devtoolsLog) {
470
+ if (event.method === 'Page.frameNavigated' && event.params.frame.id === mainFrameId) {
471
+ const {url} = event.params.frame;
472
+ // Only set requestedUrl on the first main frame navigation.
473
+ if (!requestedUrl) requestedUrl = url;
474
+ mainDocumentUrl = url;
475
+ }
476
+ }
477
+ if (!requestedUrl || !mainDocumentUrl) throw new Error('No main frame navigations found');
478
+
479
+ const initialRequest = NetworkAnalyzer.findResourceForUrl(networkRecords, requestedUrl);
480
+ if (initialRequest?.redirects?.length) requestedUrl = initialRequest.redirects[0].url;
481
+
482
+ return {requestedUrl, mainDocumentUrl};
483
+ }
484
+
485
+ /**
486
+ * @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog, URL: LH.Artifacts['URL']}} data
468
487
  * @param {LH.Artifacts.ComputedContext} context
469
488
  * @return {Promise<Node>}
470
489
  */
471
490
  static async compute_(data, context) {
472
- const trace = data.trace;
473
- const devtoolsLog = data.devtoolsLog;
491
+ const {trace, devtoolsLog} = data;
474
492
  const [processedTrace, networkRecords] = await Promise.all([
475
493
  ProcessedTrace.request(trace, context),
476
494
  NetworkRecords.request(devtoolsLog, context),
477
495
  ]);
478
496
 
479
- return PageDependencyGraph.createGraph(processedTrace, networkRecords);
497
+ // COMPAT: Backport for pre-10.0 clients that don't pass the URL artifact here (e.g. pubads).
498
+ // Calculates the URL artifact from the processed trace and DT log.
499
+ const URL = data.URL ||
500
+ PageDependencyGraph.getDocumentUrls(devtoolsLog, networkRecords, processedTrace);
501
+
502
+ return PageDependencyGraph.createGraph(processedTrace, networkRecords, URL);
480
503
  }
481
504
  }
482
505
 
483
- module.exports = makeComputedArtifact(PageDependencyGraph, ['devtoolsLog', 'trace']);
506
+ module.exports = makeComputedArtifact(PageDependencyGraph, ['devtoolsLog', 'trace', 'URL']);
484
507
 
485
508
  /**
486
509
  * @typedef {Object} NetworkNodeOutput
@@ -15,7 +15,6 @@
15
15
  * @property {LH.Gatherer.GatherMode} gatherMode
16
16
  * @property {Map<string, LH.ArbitraryEqualityMap>} computedCache
17
17
  * @property {LH.Config.Settings} settings
18
- * @property {string} url
19
18
  */
20
19
 
21
20
  /** @typedef {Record<string, Promise<any>>} IntermediateArtifacts */
@@ -75,7 +74,6 @@ async function collectPhaseArtifacts(options) {
75
74
  gatherMode,
76
75
  computedCache,
77
76
  settings,
78
- url,
79
77
  } = options;
80
78
  const priorPhase = phaseToPriorPhase[phase];
81
79
  const priorPhaseArtifacts = (priorPhase && artifactState[priorPhase]) || {};
@@ -92,7 +90,6 @@ async function collectPhaseArtifacts(options) {
92
90
  : /** @type {Dependencies} */ ({});
93
91
 
94
92
  return gatherer[phase]({
95
- url,
96
93
  gatherMode,
97
94
  driver,
98
95
  baseArtifacts,
@@ -46,7 +46,6 @@ async function snapshotGather(options) {
46
46
  const artifactDefinitions = config.artifacts || [];
47
47
  const artifactState = getEmptyArtifactState();
48
48
  await collectPhaseArtifacts({
49
- url,
50
49
  phase: 'getArtifact',
51
50
  gatherMode: 'snapshot',
52
51
  driver,
@@ -37,7 +37,6 @@ async function startTimespanGather(options) {
37
37
  const artifactState = getEmptyArtifactState();
38
38
  /** @type {Omit<import('./runner-helpers.js').CollectPhaseArtifactOptions, 'phase'>} */
39
39
  const phaseOptions = {
40
- url: initialUrl,
41
40
  driver,
42
41
  artifactDefinitions,
43
42
  artifactState,
@@ -54,7 +53,6 @@ async function startTimespanGather(options) {
54
53
  return {
55
54
  async endTimespanGather() {
56
55
  const finalUrl = await driver.url();
57
- phaseOptions.url = finalUrl;
58
56
 
59
57
  const runnerOptions = {config, computedCache};
60
58
  const artifacts = await Runner.gather(
@@ -88,6 +88,7 @@ class CriConnection extends Connection {
88
88
  path: '/json/' + command,
89
89
  }, response => {
90
90
  let data = '';
91
+ response.setEncoding('utf8');
91
92
  response.on('data', chunk => {
92
93
  data += chunk;
93
94
  });
@@ -97,7 +97,8 @@ class ExecutionContext {
97
97
  .catch(${pageFunctions.wrapRuntimeEvalErrorInBrowserString})
98
98
  .then(resolve);
99
99
  });
100
- }())`,
100
+ }())
101
+ //# sourceURL=_lighthouse-eval.js`,
101
102
  includeCommandLineAPI: true,
102
103
  awaitPromise: true,
103
104
  returnByValue: true,
@@ -195,7 +196,8 @@ class ExecutionContext {
195
196
  ${ExecutionContext._cachedNativesPreamble};
196
197
  ${depsSerialized};
197
198
  (${mainFn})(${argsSerialized});
198
- })()`;
199
+ })()
200
+ //# sourceURL=_lighthouse-eval.js`;
199
201
 
200
202
  await this._session.sendCommand('Page.addScriptToEvaluateOnNewDocument', {source: expression});
201
203
  }
@@ -50,12 +50,13 @@ class JsUsage extends FRGatherer {
50
50
  const usageByScriptId = {};
51
51
 
52
52
  for (const scriptUsage of this._scriptUsages) {
53
- // If `url` is blank, that means the script was anonymous (eval, new Function, onload, ...).
54
- // Or, it's because it was code Lighthouse over the protocol via `Runtime.evaluate`.
55
- // We currently don't consider coverage of anonymous scripts, and we definitely don't want
56
- // coverage of code Lighthouse ran to inspect the page, so we ignore this ScriptCoverage if
57
- // url is blank.
58
- if (scriptUsage.url === '') {
53
+ // If `url` is blank, that means the script was dynamically
54
+ // created (eval, new Function, onload, ...)
55
+ if (scriptUsage.url === '' || scriptUsage.url === '_lighthouse-eval.js') {
56
+ // We currently don't consider coverage of dynamic scripts, and we definitely don't want
57
+ // coverage of code Lighthouse ran to inspect the page, so we ignore this ScriptCoverage.
58
+ // Audits would work the same without this, it is only an optimization (not tracking coverage
59
+ // for scripts we don't care about).
59
60
  continue;
60
61
  }
61
62
 
@@ -28,6 +28,23 @@ async function runInSeriesOrParallel(values, promiseMapper, runInSeries) {
28
28
  }
29
29
  }
30
30
 
31
+ /**
32
+ * Returns true if the script was created via our own calls
33
+ * to Runtime.evaluate.
34
+ * @param {LH.Crdp.Debugger.ScriptParsedEvent} script
35
+ */
36
+ function isLighthouseRuntimeEvaluateScript(script) {
37
+ // Scripts created by Runtime.evaluate that run on the main session/frame
38
+ // result in an empty string for the embedderName.
39
+ // Or, it means the script was dynamically created (eval, new Function, onload, ...)
40
+ if (!script.embedderName) return true;
41
+
42
+ // Otherwise, when running our own code inside other frames, the embedderName
43
+ // is set to the frame's url. In that case, we rely on the special sourceURL that
44
+ // we set.
45
+ return script.hasSourceURL && script.url === '_lighthouse-eval.js';
46
+ }
47
+
31
48
  /**
32
49
  * @fileoverview Gets JavaScript file contents.
33
50
  */
@@ -68,8 +85,9 @@ class Scripts extends FRGatherer {
68
85
  // it also blocks scripts from the same origin but that happen to run in a different process,
69
86
  // like a worker.
70
87
  if (event.method === 'Debugger.scriptParsed' && !sessionId) {
71
- // Events without an embedderName (read: a url) are for JS that we ran over the protocol.
72
- if (event.params.embedderName) this._scriptParsedEvents.push(event.params);
88
+ if (!isLighthouseRuntimeEvaluateScript(event.params)) {
89
+ this._scriptParsedEvents.push(event.params);
90
+ }
73
91
  }
74
92
  }
75
93
 
@@ -46,7 +46,8 @@ class RobotsTxt extends FRGatherer {
46
46
  });
47
47
  }
48
48
 
49
- const robotsUrl = new URL('/robots.txt', passContext.url).href;
49
+ const {finalUrl} = passContext.baseArtifacts.URL;
50
+ const robotsUrl = new URL('/robots.txt', finalUrl).href;
50
51
  await passContext.driver.fetcher.enable();
51
52
  return passContext.driver.fetcher.fetchResource(robotsUrl)
52
53
  .catch(err => ({status: null, content: null, errorMessage: err.message}));
@@ -94,8 +94,8 @@ class WebAppManifest extends FRGatherer {
94
94
  */
95
95
  getArtifact(context) {
96
96
  const driver = context.driver;
97
-
98
- return WebAppManifest.getWebAppManifest(driver.defaultSession, context.url);
97
+ const {finalUrl} = context.baseArtifacts.URL;
98
+ return WebAppManifest.getWebAppManifest(driver.defaultSession, finalUrl);
99
99
  }
100
100
  }
101
101
 
@@ -6,7 +6,6 @@
6
6
  'use strict';
7
7
 
8
8
  const INITIAL_CWD = 14 * 1024;
9
- const NetworkRequest = require('../../network-request.js');
10
9
  const URL = require('../../url-shim.js');
11
10
 
12
11
  // Assume that 40% of TTFB was server response time by default for static assets
@@ -434,40 +433,20 @@ class NetworkAnalyzer {
434
433
 
435
434
  /**
436
435
  * @param {Array<LH.Artifacts.NetworkRequest>} records
437
- * @param {string} [finalURL]
438
- * @return {LH.Artifacts.NetworkRequest}
439
- */
440
- static findMainDocument(records, finalURL) {
441
- const mainDocument = NetworkAnalyzer.findOptionalMainDocument(records, finalURL);
442
- if (!mainDocument) throw new Error('Unable to identify the main resource');
443
- return mainDocument;
444
- }
445
-
446
- /**
447
- * @param {Array<LH.Artifacts.NetworkRequest>} records
448
- * @param {string} [finalURL]
436
+ * @param {string} resourceUrl
449
437
  * @return {LH.Artifacts.NetworkRequest|undefined}
450
438
  */
451
- static findOptionalMainDocument(records, finalURL) {
452
- // Try to find an exact match with the final URL first if we have one
453
- if (finalURL) {
454
- // equalWithExcludedFragments is expensive, so check that the finalUrl starts with the request first
455
- const mainResource = records.find(request => finalURL.startsWith(request.url) &&
456
- URL.equalWithExcludedFragments(request.url, finalURL));
457
- if (mainResource) return mainResource;
458
- // TODO: beacon !mainResource to Sentry, https://github.com/GoogleChrome/lighthouse/issues/7041
459
- }
460
-
461
- const documentRequests = records.filter(record => record.resourceType ===
462
- NetworkRequest.TYPES.Document);
463
- if (!documentRequests.length) return undefined;
464
- // The main document is the earliest document request, using position in networkRecords array to break ties.
465
- return documentRequests.reduce((min, r) => (r.startTime < min.startTime ? r : min));
439
+ static findResourceForUrl(records, resourceUrl) {
440
+ // equalWithExcludedFragments is expensive, so check that the resourceUrl starts with the request url first
441
+ return records.find(request =>
442
+ resourceUrl.startsWith(request.url) &&
443
+ URL.equalWithExcludedFragments(request.url, resourceUrl)
444
+ );
466
445
  }
467
446
 
468
447
  /**
469
448
  * Resolves redirect chain given a main document.
470
- * See: {@link NetworkAnalyzer.findMainDocument}) for how to retrieve main document.
449
+ * See: {@link NetworkAnalyzer.findResourceForUrl}) for how to retrieve main document.
471
450
  *
472
451
  * @param {LH.Artifacts.NetworkRequest} request
473
452
  * @return {LH.Artifacts.NetworkRequest}
@@ -7,6 +7,7 @@
7
7
 
8
8
  const LHError = require('./lh-error.js');
9
9
  const NetworkAnalyzer = require('./dependency-graph/simulator/network-analyzer.js');
10
+ const NetworkRequest = require('./network-request.js');
10
11
 
11
12
  /**
12
13
  * Returns an error if the original network request failed or wasn't found.
@@ -100,10 +101,18 @@ function getNonHtmlError(finalRecord) {
100
101
  function getPageLoadError(navigationError, context) {
101
102
  const {url, loadFailureMode, networkRecords} = context;
102
103
  /** @type {LH.Artifacts.NetworkRequest|undefined} */
103
- let mainRecord;
104
- try {
105
- mainRecord = NetworkAnalyzer.findMainDocument(networkRecords, url);
106
- } catch (_) {}
104
+ let mainRecord = NetworkAnalyzer.findResourceForUrl(networkRecords, url);
105
+
106
+ // If the url doesn't give us a network request, it's possible we landed on a chrome-error:// page
107
+ // In this case, just get the first document request.
108
+ if (!mainRecord) {
109
+ const documentRequests = networkRecords.filter(record =>
110
+ record.resourceType === NetworkRequest.TYPES.Document
111
+ );
112
+ if (documentRequests.length) {
113
+ mainRecord = documentRequests.reduce((min, r) => (r.startTime < min.startTime ? r : min));
114
+ }
115
+ }
107
116
 
108
117
  // MIME Type is only set on the final redirected document request. Use this for the HTML check instead of root.
109
118
  let finalRecord;
@@ -318,24 +318,26 @@ class Util {
318
318
  }
319
319
 
320
320
  const MAX_LENGTH = 64;
321
- // Always elide hexadecimal hash
322
- name = name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, `$1${ELLIPSIS}`);
323
- // Also elide other hash-like mixed-case strings
324
- name = name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,
325
- `$1${ELLIPSIS}`);
326
- // Also elide long number sequences
327
- name = name.replace(/(\d{3})\d{6,}/g, `$1${ELLIPSIS}`);
328
- // Merge any adjacent ellipses
329
- name = name.replace(/\u2026+/g, ELLIPSIS);
330
-
331
- // Elide query params first
332
- if (name.length > MAX_LENGTH && name.includes('?')) {
333
- // Try to leave the first query parameter intact
334
- name = name.replace(/\?([^=]*)(=)?.*/, `?$1$2${ELLIPSIS}`);
335
-
336
- // Remove it all if it's still too long
337
- if (name.length > MAX_LENGTH) {
338
- name = name.replace(/\?.*/, `?${ELLIPSIS}`);
321
+ if (parsedUrl.protocol !== 'data:') {
322
+ // Always elide hexadecimal hash
323
+ name = name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, `$1${ELLIPSIS}`);
324
+ // Also elide other hash-like mixed-case strings
325
+ name = name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,
326
+ `$1${ELLIPSIS}`);
327
+ // Also elide long number sequences
328
+ name = name.replace(/(\d{3})\d{6,}/g, `$1${ELLIPSIS}`);
329
+ // Merge any adjacent ellipses
330
+ name = name.replace(/\u2026+/g, ELLIPSIS);
331
+
332
+ // Elide query params first
333
+ if (name.length > MAX_LENGTH && name.includes('?')) {
334
+ // Try to leave the first query parameter intact
335
+ name = name.replace(/\?([^=]*)(=)?.*/, `?$1$2${ELLIPSIS}`);
336
+
337
+ // Remove it all if it's still too long
338
+ if (name.length > MAX_LENGTH) {
339
+ name = name.replace(/\?.*/, `?${ELLIPSIS}`);
340
+ }
339
341
  }
340
342
  }
341
343
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lighthouse",
3
- "version": "9.5.0-dev.20220329",
3
+ "version": "9.5.0-dev.20220401",
4
4
  "description": "Automated auditing, performance metrics, and best practices for the web.",
5
5
  "main": "./lighthouse-core/index.js",
6
6
  "bin": {
@@ -89,8 +89,8 @@
89
89
  "compile-proto": "protoc --python_out=./ ./proto/lighthouse-result.proto && mv ./proto/*_pb2.py ./proto/scripts || (echo \"❌ Install protobuf ≥ 3.7.1 to compile the proto file.\" && false)",
90
90
  "build-proto-roundtrip": "mkdir -p .tmp && cross-env PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2 python proto/scripts/json_roundtrip_via_proto.py",
91
91
  "static-server": "node lighthouse-cli/test/fixtures/static-server.js",
92
- "serve-dist": "cd dist && python -m SimpleHTTPServer",
93
- "serve-gh-pages": "cd dist/gh-pages && python -m SimpleHTTPServer",
92
+ "serve-dist": "cd dist && python3 -m http.server",
93
+ "serve-gh-pages": "cd dist/gh-pages && python3 -m http.server",
94
94
  "serve-treemap": "yarn serve-gh-pages",
95
95
  "serve-viewer": "yarn serve-gh-pages",
96
96
  "flow-report": "yarn build-report --flow && node ./lighthouse-core/scripts/build-test-flow-report.js"
@@ -203,7 +203,7 @@
203
203
  "robots-parser": "^3.0.0",
204
204
  "semver": "^5.3.0",
205
205
  "speedline-core": "^1.4.3",
206
- "third-party-web": "^0.12.7",
206
+ "third-party-web": "^0.15.0",
207
207
  "ws": "^7.0.0",
208
208
  "yargs": "^17.3.1",
209
209
  "yargs-parser": "^21.0.0"
@@ -315,24 +315,26 @@ class Util {
315
315
  }
316
316
 
317
317
  const MAX_LENGTH = 64;
318
- // Always elide hexadecimal hash
319
- name = name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, `$1${ELLIPSIS}`);
320
- // Also elide other hash-like mixed-case strings
321
- name = name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,
322
- `$1${ELLIPSIS}`);
323
- // Also elide long number sequences
324
- name = name.replace(/(\d{3})\d{6,}/g, `$1${ELLIPSIS}`);
325
- // Merge any adjacent ellipses
326
- name = name.replace(/\u2026+/g, ELLIPSIS);
327
-
328
- // Elide query params first
329
- if (name.length > MAX_LENGTH && name.includes('?')) {
330
- // Try to leave the first query parameter intact
331
- name = name.replace(/\?([^=]*)(=)?.*/, `?$1$2${ELLIPSIS}`);
332
-
333
- // Remove it all if it's still too long
334
- if (name.length > MAX_LENGTH) {
335
- name = name.replace(/\?.*/, `?${ELLIPSIS}`);
318
+ if (parsedUrl.protocol !== 'data:') {
319
+ // Always elide hexadecimal hash
320
+ name = name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, `$1${ELLIPSIS}`);
321
+ // Also elide other hash-like mixed-case strings
322
+ name = name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,
323
+ `$1${ELLIPSIS}`);
324
+ // Also elide long number sequences
325
+ name = name.replace(/(\d{3})\d{6,}/g, `$1${ELLIPSIS}`);
326
+ // Merge any adjacent ellipses
327
+ name = name.replace(/\u2026+/g, ELLIPSIS);
328
+
329
+ // Elide query params first
330
+ if (name.length > MAX_LENGTH && name.includes('?')) {
331
+ // Try to leave the first query parameter intact
332
+ name = name.replace(/\?([^=]*)(=)?.*/, `?$1$2${ELLIPSIS}`);
333
+
334
+ // Remove it all if it's still too long
335
+ if (name.length > MAX_LENGTH) {
336
+ name = name.replace(/\?.*/, `?${ELLIPSIS}`);
337
+ }
336
338
  }
337
339
  }
338
340
 
@@ -1272,7 +1272,7 @@
1272
1272
  "message": "Fonts with `font-display: optional` are preloaded"
1273
1273
  },
1274
1274
  "lighthouse-core/audits/preload-lcp-image.js | description": {
1275
- "message": "Preload the image used by the LCP element in order to improve your LCP time. [Learn more](https://web.dev/optimize-lcp/#preload-important-resources)."
1275
+ "message": "If the LCP element is dynamically added to the page, you should preload the image in order to improve LCP. [Learn more](https://web.dev/optimize-lcp/#preload-important-resources)."
1276
1276
  },
1277
1277
  "lighthouse-core/audits/preload-lcp-image.js | title": {
1278
1278
  "message": "Preload Largest Contentful Paint image"
@@ -1272,7 +1272,7 @@
1272
1272
  "message": "F̂ón̂t́ŝ ẃît́ĥ `font-display: optional` ár̂é p̂ŕêĺôád̂éd̂"
1273
1273
  },
1274
1274
  "lighthouse-core/audits/preload-lcp-image.js | description": {
1275
- "message": "P̂ŕêĺôád̂ t́ĥé îḿâǵê úŝéd̂ b́ŷ t́ĥé L̂ĆP̂ él̂ém̂én̂t́ îń ôŕd̂ér̂ t́ô ím̂ṕr̂óv̂é ŷóûŕ L̂ĆP̂ t́îḿê. [Ĺêár̂ń m̂ór̂é](https://web.dev/optimize-lcp/#preload-important-resources)."
1275
+ "message": "Îf́ t̂h́ ĹĈṔ êĺêêń íŝ d́ŷńâîćĺl̂ âd́d̂éd̂ t́ô t́ĥé p̂áĝé, ŷóû śĥóûĺd̂ ṕr̂él̂óâd́ t̂h́ê ím̂áĝé îń ôŕd̂ér̂ t́ô ím̂ṕr̂óv̂é L̂ĆP̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/optimize-lcp/#preload-important-resources)."
1276
1276
  },
1277
1277
  "lighthouse-core/audits/preload-lcp-image.js | title": {
1278
1278
  "message": "P̂ŕêĺôád̂ Ĺâŕĝéŝt́ Ĉón̂t́êńt̂f́ûĺ P̂áîńt̂ ím̂áĝé"
@@ -641,6 +641,7 @@ declare module Artifacts {
641
641
  settings: Immutable<Config.Settings>;
642
642
  gatherContext: Artifacts['GatherContext'];
643
643
  simulator?: InstanceType<typeof LanternSimulator>;
644
+ URL: Artifacts['URL'];
644
645
  }
645
646
 
646
647
  interface MetricComputationData extends MetricComputationDataInput {
@@ -47,8 +47,6 @@ declare module Gatherer {
47
47
 
48
48
  /** The limited context interface shared between pre and post Fraggle Rock Lighthouse. */
49
49
  interface FRTransitionalContext<TDependencies extends DependencyKey = DefaultDependenciesKey> {
50
- /** The URL of the page that is currently active. Might be `about:blank` in the before phases */
51
- url: string;
52
50
  /** The gather mode Lighthouse is currently in. */
53
51
  gatherMode: GatherMode;
54
52
  /** The connection to the page being analyzed. */