lighthouse 9.5.0-dev.20220607 → 9.6.2
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.
- package/dist/report/bundle.esm.js +467 -520
- package/dist/report/flow.js +22 -22
- package/dist/report/standalone.js +19 -19
- package/flow-report/src/summary/category.tsx +1 -1
- package/flow-report/src/topbar.tsx +2 -10
- package/flow-report/src/util.ts +1 -1
- package/flow-report/test/topbar-test.tsx +8 -7
- package/jest.config.js +1 -1
- package/lighthouse-cli/.eslintrc.cjs +4 -3
- package/lighthouse-cli/bin.js +1 -0
- package/lighthouse-cli/cli-flags.js +4 -3
- package/lighthouse-cli/commands/commands.js +1 -0
- package/lighthouse-cli/commands/list-audits.js +1 -0
- package/lighthouse-cli/commands/list-locales.js +1 -0
- package/lighthouse-cli/commands/list-trace-categories.js +1 -0
- package/lighthouse-cli/index.js +1 -0
- package/lighthouse-cli/printer.js +1 -0
- package/lighthouse-cli/run.js +24 -9
- package/lighthouse-cli/sentry-prompt.js +1 -0
- package/lighthouse-cli/test/smokehouse/core-tests.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/lib.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -0
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +23 -109
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +3 -2
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/devtools.js +19 -28
- package/lighthouse-cli/test/smokehouse/report-assert.js +4 -3
- package/lighthouse-cli/test/smokehouse/smokehouse.js +1 -1
- package/lighthouse-cli/test/smokehouse/version-check-test.js +3 -0
- package/lighthouse-cli/test/smokehouse/version-check.js +1 -0
- package/lighthouse-core/audits/accessibility/accesskeys.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-allowed-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-hidden-body.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-hidden-focus.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-input-field-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-children.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-parent.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-roles.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-toggle-field-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-valid-attr-value.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-valid-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/button-name.js +1 -1
- package/lighthouse-core/audits/accessibility/bypass.js +1 -1
- package/lighthouse-core/audits/accessibility/color-contrast.js +1 -1
- package/lighthouse-core/audits/accessibility/definition-list.js +1 -1
- package/lighthouse-core/audits/accessibility/dlitem.js +1 -1
- package/lighthouse-core/audits/accessibility/document-title.js +1 -1
- package/lighthouse-core/audits/accessibility/duplicate-id-active.js +1 -1
- package/lighthouse-core/audits/accessibility/duplicate-id-aria.js +1 -1
- package/lighthouse-core/audits/accessibility/form-field-multiple-labels.js +1 -1
- package/lighthouse-core/audits/accessibility/frame-title.js +1 -1
- package/lighthouse-core/audits/accessibility/heading-order.js +1 -1
- package/lighthouse-core/audits/accessibility/html-has-lang.js +1 -1
- package/lighthouse-core/audits/accessibility/html-lang-valid.js +1 -1
- package/lighthouse-core/audits/accessibility/image-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/input-image-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/label.js +1 -1
- package/lighthouse-core/audits/accessibility/link-name.js +1 -1
- package/lighthouse-core/audits/accessibility/list.js +1 -1
- package/lighthouse-core/audits/accessibility/listitem.js +5 -5
- package/lighthouse-core/audits/accessibility/meta-refresh.js +1 -1
- package/lighthouse-core/audits/accessibility/meta-viewport.js +1 -1
- package/lighthouse-core/audits/accessibility/object-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/tabindex.js +1 -1
- package/lighthouse-core/audits/accessibility/td-headers-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/th-has-data-cells.js +1 -1
- package/lighthouse-core/audits/accessibility/valid-lang.js +1 -1
- package/lighthouse-core/audits/accessibility/video-caption.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +12 -11
- package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +24 -22
- package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +3 -2
- package/lighthouse-core/audits/byte-efficiency/unminified-css.js +5 -3
- package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +11 -10
- package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -0
- package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +8 -11
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
- package/lighthouse-core/audits/deprecations.js +598 -8
- package/lighthouse-core/audits/diagnostics.js +3 -4
- package/lighthouse-core/audits/dobetterweb/doctype.js +9 -20
- package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +1 -1
- package/lighthouse-core/audits/dobetterweb/no-document-write.js +1 -1
- package/lighthouse-core/audits/dobetterweb/notification-on-start.js +1 -1
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -2
- package/lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js +1 -1
- package/lighthouse-core/audits/errors-in-console.js +2 -2
- package/lighthouse-core/audits/long-tasks.js +2 -3
- package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -2
- package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/interactive.js +2 -3
- package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -3
- package/lighthouse-core/audits/metrics/speed-index.js +2 -3
- package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -3
- package/lighthouse-core/audits/metrics.js +2 -3
- package/lighthouse-core/audits/no-unload-listeners.js +15 -7
- package/lighthouse-core/audits/predictive-perf.js +1 -2
- package/lighthouse-core/audits/preload-lcp-image.js +3 -3
- package/lighthouse-core/audits/redirects.js +1 -1
- package/lighthouse-core/audits/script-treemap-data.js +45 -45
- package/lighthouse-core/audits/seo/http-status-code.js +4 -2
- package/lighthouse-core/audits/seo/link-text.js +0 -2
- package/lighthouse-core/audits/server-response-time.js +17 -2
- package/lighthouse-core/audits/service-worker.js +2 -7
- package/lighthouse-core/audits/timing-budget.js +2 -3
- package/lighthouse-core/audits/uses-rel-preconnect.js +1 -1
- package/lighthouse-core/audits/uses-rel-preload.js +1 -1
- package/lighthouse-core/audits/valid-source-maps.js +14 -12
- package/lighthouse-core/audits/violation-audit.js +1 -1
- package/lighthouse-core/audits/work-during-interaction.js +2 -2
- package/lighthouse-core/computed/critical-request-chains.js +9 -5
- package/lighthouse-core/computed/js-bundles.js +11 -11
- package/lighthouse-core/computed/main-resource.js +2 -3
- package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
- package/lighthouse-core/computed/metrics/first-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/first-meaningful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/interactive.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-interactive.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-max-potential-fid.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-metric.js +5 -3
- package/lighthouse-core/computed/metrics/lantern-speed-index.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-total-blocking-time.js +1 -1
- package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
- package/lighthouse-core/computed/metrics/largest-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/max-potential-fid.js +1 -1
- package/lighthouse-core/computed/metrics/metric.js +0 -1
- package/lighthouse-core/computed/metrics/speed-index.js +1 -1
- package/lighthouse-core/computed/metrics/timing-summary.js +6 -13
- package/lighthouse-core/computed/metrics/total-blocking-time.js +1 -1
- package/lighthouse-core/computed/module-duplication.js +5 -6
- package/lighthouse-core/computed/page-dependency-graph.js +28 -55
- package/lighthouse-core/computed/resource-summary.js +5 -5
- package/lighthouse-core/computed/unused-css.js +7 -6
- package/lighthouse-core/computed/unused-javascript-summary.js +36 -16
- package/lighthouse-core/config/budget.js +2 -2
- package/lighthouse-core/config/default-config.js +1 -2
- package/lighthouse-core/fraggle-rock/api.js +1 -1
- package/lighthouse-core/fraggle-rock/config/default-config.js +0 -3
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +3 -6
- package/lighthouse-core/fraggle-rock/gather/driver.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +26 -51
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
- package/lighthouse-core/fraggle-rock/gather/session.js +22 -23
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -5
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +6 -6
- package/lighthouse-core/gather/connections/cri.js +1 -5
- package/lighthouse-core/gather/driver/execution-context.js +2 -5
- package/lighthouse-core/gather/driver/navigation.js +10 -13
- package/lighthouse-core/gather/driver/network-monitor.js +3 -16
- package/lighthouse-core/gather/driver.js +1 -6
- package/lighthouse-core/gather/fetcher.js +210 -34
- package/lighthouse-core/gather/gather-runner.js +17 -13
- package/lighthouse-core/gather/gatherers/accessibility.js +4 -16
- package/lighthouse-core/gather/gatherers/console-messages.js +2 -4
- package/lighthouse-core/gather/gatherers/dobetterweb/doctype.js +2 -4
- package/lighthouse-core/gather/gatherers/full-page-screenshot.js +2 -3
- package/lighthouse-core/gather/gatherers/iframe-elements.js +1 -4
- package/lighthouse-core/gather/gatherers/image-elements.js +0 -2
- package/lighthouse-core/gather/gatherers/js-usage.js +87 -12
- package/lighthouse-core/gather/gatherers/link-elements.js +14 -12
- package/lighthouse-core/gather/gatherers/main-document-content.js +8 -8
- package/lighthouse-core/gather/gatherers/script-elements.js +56 -7
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +30 -2
- package/lighthouse-core/gather/gatherers/source-maps.js +1 -8
- package/lighthouse-core/gather/gatherers/web-app-manifest.js +2 -2
- package/lighthouse-core/index.js +2 -26
- package/lighthouse-core/lib/cdt/generated/SourceMap.js +1 -1
- package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +29 -8
- package/lighthouse-core/lib/navigation-error.js +4 -13
- package/lighthouse-core/lib/page-functions.js +1 -3
- package/lighthouse-core/lib/script-helpers.js +6 -11
- package/lighthouse-core/lib/url-shim.js +2 -2
- package/lighthouse-core/runner.js +5 -0
- package/lighthouse-core/scripts/manual-chrome-launcher.js +1 -0
- package/lighthouse-core/util-commonjs.js +6 -8
- package/package.json +13 -13
- package/readme.md +1 -1
- package/report/.eslintrc.cjs +1 -3
- package/report/assets/styles.css +5 -10
- package/report/assets/templates.html +9 -10
- package/report/clients/bundle.js +1 -0
- package/report/clients/standalone.js +1 -0
- package/report/generator/report-generator.js +21 -46
- package/report/renderer/api.js +2 -0
- package/report/renderer/category-renderer.js +24 -20
- package/report/renderer/components.js +304 -303
- package/report/renderer/crc-details-renderer.js +24 -21
- package/report/renderer/details-renderer.js +12 -12
- package/report/renderer/dom.js +7 -6
- package/report/renderer/drop-down-menu.js +1 -0
- package/report/renderer/element-screenshot-renderer.js +5 -1
- package/report/renderer/features-util.js +1 -0
- package/report/renderer/i18n.js +62 -118
- package/report/renderer/logger.js +1 -0
- package/report/renderer/open-tab.js +3 -1
- package/report/renderer/performance-category-renderer.js +11 -10
- package/report/renderer/pwa-category-renderer.js +4 -3
- package/report/renderer/report-renderer.js +17 -17
- package/report/renderer/report-ui-features.js +1 -0
- package/report/renderer/snippet-renderer.js +3 -2
- package/report/renderer/swap-locale-feature.js +1 -0
- package/report/renderer/text-encoding.js +1 -0
- package/report/renderer/topbar-features.js +1 -0
- package/report/renderer/util.js +6 -7
- package/report/test/clients/bundle-test.js +5 -0
- package/report/test/generator/file-namer-test.js +1 -0
- package/report/test/generator/report-generator-test.js +20 -25
- package/report/test/renderer/category-renderer-test.js +4 -3
- package/report/test/renderer/components-test.js +3 -0
- package/report/test/renderer/crc-details-renderer-test.js +3 -0
- package/report/test/renderer/details-renderer-test.js +3 -49
- package/report/test/renderer/dom-test.js +3 -0
- package/report/test/renderer/element-screenshot-renderer-test.js +6 -3
- package/report/test/renderer/i18n-test.js +25 -70
- package/report/test/renderer/performance-category-renderer-test.js +5 -14
- package/report/test/renderer/pwa-category-renderer-test.js +4 -3
- package/report/test/renderer/report-renderer-axe-test.js +4 -3
- package/report/test/renderer/report-renderer-test.js +4 -3
- package/report/test/renderer/report-ui-features-test.js +4 -3
- package/report/test/renderer/snippet-renderer-test.js +3 -0
- package/report/test/renderer/text-encoding-test.js +3 -0
- package/report/test/renderer/util-test.js +5 -4
- package/report/test-assets/faux-psi.js +1 -2
- package/shared/localization/format.js +3 -7
- package/shared/localization/locales/en-US.json +238 -55
- package/shared/localization/locales/en-XL.json +238 -55
- package/shared/test/localization/format-test.js +2 -8
- package/shared/test/localization/locales-test.js +2 -0
- package/shared/test/localization/swap-locale-test.js +2 -0
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -0
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -0
- package/tsconfig.json +0 -1
- package/types/artifacts.d.ts +8 -47
- package/types/config.d.ts +0 -2
- package/types/externs.d.ts +2 -3
- package/types/gatherer.d.ts +2 -1
- package/types/global-lh.d.ts +0 -3
- package/types/lhr/lhr.d.ts +2 -2
- package/types/lhr/treemap.d.ts +1 -0
- package/changelog.md +0 -5902
- package/lighthouse-core/audits/script-elements-test-audit.js +0 -30
- package/lighthouse-core/gather/gatherers/scripts.js +0 -154
- package/lighthouse-core/scripts/package.json +0 -4
- package/report/test/.eslintrc.cjs +0 -11
- package/shared/test/localization/.eslintrc.cjs +0 -11
|
@@ -8,14 +8,13 @@
|
|
|
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');
|
|
11
12
|
const TracingProcessor = require('../lib/tracehouse/trace-processor.js');
|
|
12
13
|
const NetworkRequest = require('../lib/network-request.js');
|
|
13
14
|
const ProcessedTrace = require('./processed-trace.js');
|
|
14
15
|
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 */
|
|
19
18
|
|
|
20
19
|
// Shorter tasks have negligible impact on simulation results.
|
|
21
20
|
const SIGNIFICANT_DUR_THRESHOLD_MS = 10;
|
|
@@ -389,25 +388,34 @@ class PageDependencyGraph {
|
|
|
389
388
|
/**
|
|
390
389
|
* @param {LH.Artifacts.ProcessedTrace} processedTrace
|
|
391
390
|
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
392
|
-
* @param {URLArtifact} URL
|
|
393
391
|
* @return {Node}
|
|
394
392
|
*/
|
|
395
|
-
static createGraph(processedTrace, networkRecords
|
|
393
|
+
static createGraph(processedTrace, networkRecords) {
|
|
396
394
|
const networkNodeOutput = PageDependencyGraph.getNetworkNodeOutput(networkRecords);
|
|
397
395
|
const cpuNodes = PageDependencyGraph.getCPUNodes(processedTrace);
|
|
398
|
-
const {requestedUrl, mainDocumentUrl} = URL;
|
|
399
|
-
if (!requestedUrl) throw new Error('requestedUrl is required to get the root request');
|
|
400
|
-
if (!mainDocumentUrl) throw new Error('mainDocumentUrl is required to get the main resource');
|
|
401
|
-
|
|
402
|
-
const rootRequest = NetworkAnalyzer.findResourceForUrl(networkRecords, requestedUrl);
|
|
403
|
-
if (!rootRequest) throw new Error('rootRequest not found');
|
|
404
|
-
const rootNode = networkNodeOutput.idToNodeMap.get(rootRequest.requestId);
|
|
405
|
-
if (!rootNode) throw new Error('rootNode not found');
|
|
406
396
|
|
|
407
|
-
|
|
408
|
-
|
|
397
|
+
// The main document request is the earliest network request *of type document*.
|
|
398
|
+
// This will be different from the root request when there are server redirects.
|
|
399
|
+
const mainDocumentRequest = NetworkAnalyzer.findMainDocument(networkRecords);
|
|
409
400
|
const mainDocumentNode = networkNodeOutput.idToNodeMap.get(mainDocumentRequest.requestId);
|
|
410
|
-
if (!mainDocumentNode)
|
|
401
|
+
if (!mainDocumentNode) {
|
|
402
|
+
// mainDocumentNode should always be found.
|
|
403
|
+
throw new Error('mainDocumentNode not found.');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// The root request is the earliest request in the main document redirect chain.
|
|
407
|
+
// Will be undefined if there were no redirects.
|
|
408
|
+
const rootRequest = mainDocumentNode.record.redirects?.[0];
|
|
409
|
+
|
|
410
|
+
let rootNode;
|
|
411
|
+
if (rootRequest) {
|
|
412
|
+
// rootNode should always be found.
|
|
413
|
+
rootNode = rootRequest && networkNodeOutput.idToNodeMap.get(rootRequest.requestId);
|
|
414
|
+
if (!rootNode) throw new Error('rootNode not found');
|
|
415
|
+
} else {
|
|
416
|
+
// Use main document as root if there were no redirects.
|
|
417
|
+
rootNode = mainDocumentNode;
|
|
418
|
+
}
|
|
411
419
|
|
|
412
420
|
PageDependencyGraph.linkNetworkNodes(rootNode, networkNodeOutput);
|
|
413
421
|
PageDependencyGraph.linkCPUNodes(rootNode, networkNodeOutput, cpuNodes);
|
|
@@ -453,58 +461,23 @@ class PageDependencyGraph {
|
|
|
453
461
|
}
|
|
454
462
|
|
|
455
463
|
/**
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
* @param {LH.DevtoolsLog} devtoolsLog
|
|
459
|
-
* @param {LH.Artifacts.NetworkRequest[]} networkRecords
|
|
460
|
-
* @param {LH.Artifacts.ProcessedTrace} processedTrace
|
|
461
|
-
* @return {URLArtifact}
|
|
462
|
-
*/
|
|
463
|
-
static getDocumentUrls(devtoolsLog, networkRecords, processedTrace) {
|
|
464
|
-
const mainFrameId = processedTrace.mainFrameIds.frameId;
|
|
465
|
-
|
|
466
|
-
/** @type {string|undefined} */
|
|
467
|
-
let requestedUrl;
|
|
468
|
-
/** @type {string|undefined} */
|
|
469
|
-
let mainDocumentUrl;
|
|
470
|
-
for (const event of devtoolsLog) {
|
|
471
|
-
if (event.method === 'Page.frameNavigated' && event.params.frame.id === mainFrameId) {
|
|
472
|
-
const {url} = event.params.frame;
|
|
473
|
-
// Only set requestedUrl on the first main frame navigation.
|
|
474
|
-
if (!requestedUrl) requestedUrl = url;
|
|
475
|
-
mainDocumentUrl = url;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
if (!requestedUrl || !mainDocumentUrl) throw new Error('No main frame navigations found');
|
|
479
|
-
|
|
480
|
-
const initialRequest = NetworkAnalyzer.findResourceForUrl(networkRecords, requestedUrl);
|
|
481
|
-
if (initialRequest?.redirects?.length) requestedUrl = initialRequest.redirects[0].url;
|
|
482
|
-
|
|
483
|
-
return {requestedUrl, mainDocumentUrl};
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog, URL: LH.Artifacts['URL']}} data
|
|
464
|
+
* @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog}} data
|
|
488
465
|
* @param {LH.Artifacts.ComputedContext} context
|
|
489
466
|
* @return {Promise<Node>}
|
|
490
467
|
*/
|
|
491
468
|
static async compute_(data, context) {
|
|
492
|
-
const
|
|
469
|
+
const trace = data.trace;
|
|
470
|
+
const devtoolsLog = data.devtoolsLog;
|
|
493
471
|
const [processedTrace, networkRecords] = await Promise.all([
|
|
494
472
|
ProcessedTrace.request(trace, context),
|
|
495
473
|
NetworkRecords.request(devtoolsLog, context),
|
|
496
474
|
]);
|
|
497
475
|
|
|
498
|
-
|
|
499
|
-
// Calculates the URL artifact from the processed trace and DT log.
|
|
500
|
-
const URL = data.URL ||
|
|
501
|
-
PageDependencyGraph.getDocumentUrls(devtoolsLog, networkRecords, processedTrace);
|
|
502
|
-
|
|
503
|
-
return PageDependencyGraph.createGraph(processedTrace, networkRecords, URL);
|
|
476
|
+
return PageDependencyGraph.createGraph(processedTrace, networkRecords);
|
|
504
477
|
}
|
|
505
478
|
}
|
|
506
479
|
|
|
507
|
-
module.exports = makeComputedArtifact(PageDependencyGraph, ['devtoolsLog', 'trace'
|
|
480
|
+
module.exports = makeComputedArtifact(PageDependencyGraph, ['devtoolsLog', 'trace']);
|
|
508
481
|
|
|
509
482
|
/**
|
|
510
483
|
* @typedef {Object} NetworkNodeOutput
|
|
@@ -35,11 +35,11 @@ class ResourceSummary {
|
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
38
|
-
* @param {
|
|
38
|
+
* @param {string} mainResourceURL
|
|
39
39
|
* @param {ImmutableObject<LH.Budget[]|null>} budgets
|
|
40
40
|
* @return {Record<LH.Budget.ResourceType, ResourceEntry>}
|
|
41
41
|
*/
|
|
42
|
-
static summarize(networkRecords,
|
|
42
|
+
static summarize(networkRecords, mainResourceURL, budgets) {
|
|
43
43
|
/** @type {Record<LH.Budget.ResourceType, ResourceEntry>} */
|
|
44
44
|
const resourceSummary = {
|
|
45
45
|
'stylesheet': {count: 0, resourceSize: 0, transferSize: 0},
|
|
@@ -52,13 +52,13 @@ class ResourceSummary {
|
|
|
52
52
|
'total': {count: 0, resourceSize: 0, transferSize: 0},
|
|
53
53
|
'third-party': {count: 0, resourceSize: 0, transferSize: 0},
|
|
54
54
|
};
|
|
55
|
-
const budget = Budget.getMatchingBudget(budgets,
|
|
55
|
+
const budget = Budget.getMatchingBudget(budgets, mainResourceURL);
|
|
56
56
|
/** @type {ReadonlyArray<string>} */
|
|
57
57
|
let firstPartyHosts = [];
|
|
58
58
|
if (budget?.options?.firstPartyHostnames) {
|
|
59
59
|
firstPartyHosts = budget.options.firstPartyHostnames;
|
|
60
60
|
} else {
|
|
61
|
-
const rootDomain = Util.getRootDomain(
|
|
61
|
+
const rootDomain = Util.getRootDomain(mainResourceURL);
|
|
62
62
|
firstPartyHosts = [`*.${rootDomain}`];
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -107,7 +107,7 @@ class ResourceSummary {
|
|
|
107
107
|
*/
|
|
108
108
|
static async compute_(data, context) {
|
|
109
109
|
const networkRecords = await NetworkRecords.request(data.devtoolsLog, context);
|
|
110
|
-
return ResourceSummary.summarize(networkRecords, data.URL, data.budgets);
|
|
110
|
+
return ResourceSummary.summarize(networkRecords, data.URL.finalUrl, data.budgets);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -120,11 +120,12 @@ class UnusedCSS {
|
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
122
|
* @param {StyleSheetInfo} stylesheetInfo The stylesheetInfo object.
|
|
123
|
+
* @param {string} pageUrl The URL of the page, used to identify inline styles.
|
|
123
124
|
* @return {LH.Audit.ByteEfficiencyItem}
|
|
124
125
|
*/
|
|
125
|
-
static mapSheetToResult(stylesheetInfo) {
|
|
126
|
+
static mapSheetToResult(stylesheetInfo, pageUrl) {
|
|
126
127
|
let url = stylesheetInfo.header.sourceURL;
|
|
127
|
-
if (!url ||
|
|
128
|
+
if (!url || url === pageUrl) {
|
|
128
129
|
const contentPreview = UnusedCSS.determineContentPreview(stylesheetInfo.content);
|
|
129
130
|
url = contentPreview;
|
|
130
131
|
}
|
|
@@ -134,20 +135,20 @@ class UnusedCSS {
|
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
/**
|
|
137
|
-
* @param {{CSSUsage: LH.Artifacts['CSSUsage'], devtoolsLog: LH.DevtoolsLog}} data
|
|
138
|
+
* @param {{CSSUsage: LH.Artifacts['CSSUsage'], URL: LH.Artifacts['URL'], devtoolsLog: LH.DevtoolsLog}} data
|
|
138
139
|
* @param {LH.Artifacts.ComputedContext} context
|
|
139
140
|
* @return {Promise<LH.Audit.ByteEfficiencyItem[]>}
|
|
140
141
|
*/
|
|
141
142
|
static async compute_(data, context) {
|
|
142
|
-
const {CSSUsage, devtoolsLog} = data;
|
|
143
|
+
const {CSSUsage, URL, devtoolsLog} = data;
|
|
143
144
|
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
|
|
144
145
|
const indexedSheets = UnusedCSS.indexStylesheetsById(CSSUsage.stylesheets, networkRecords);
|
|
145
146
|
UnusedCSS.indexUsedRules(CSSUsage.rules, indexedSheets);
|
|
146
147
|
|
|
147
148
|
const items = Object.keys(indexedSheets)
|
|
148
|
-
.map(sheetId => UnusedCSS.mapSheetToResult(indexedSheets[sheetId]));
|
|
149
|
+
.map(sheetId => UnusedCSS.mapSheetToResult(indexedSheets[sheetId], URL.finalUrl));
|
|
149
150
|
return items;
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
module.exports = makeComputedArtifact(UnusedCSS, ['CSSUsage', 'devtoolsLog']);
|
|
154
|
+
module.exports = makeComputedArtifact(UnusedCSS, ['CSSUsage', 'URL', 'devtoolsLog']);
|
|
@@ -16,14 +16,14 @@ const makeComputedArtifact = require('./computed-artifact.js');
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @typedef ComputeInput
|
|
19
|
-
* @property {string}
|
|
20
|
-
* @property {Omit<LH.Crdp.Profiler.ScriptCoverage, 'url'
|
|
19
|
+
* @property {string} url
|
|
20
|
+
* @property {Array<Omit<LH.Crdp.Profiler.ScriptCoverage, 'url'>>} scriptCoverages
|
|
21
21
|
* @property {LH.Artifacts.Bundle=} bundle
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* @typedef Summary
|
|
26
|
-
* @property {string}
|
|
26
|
+
* @property {string} url
|
|
27
27
|
* @property {number} wastedBytes
|
|
28
28
|
* @property {number} totalBytes
|
|
29
29
|
* @property {number} wastedBytes
|
|
@@ -68,24 +68,43 @@ class UnusedJavascriptSummary {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* @param {string}
|
|
72
|
-
* @param {
|
|
71
|
+
* @param {string} url
|
|
72
|
+
* @param {ReturnType<typeof UnusedJavascriptSummary.determineLengths>} lengths
|
|
73
73
|
* @return {Summary}
|
|
74
74
|
*/
|
|
75
|
-
static createItem(
|
|
76
|
-
const wastedRatio = (
|
|
77
|
-
const wastedBytes = Math.round(
|
|
75
|
+
static createItem(url, lengths) {
|
|
76
|
+
const wastedRatio = (lengths.unused / lengths.content) || 0;
|
|
77
|
+
const wastedBytes = Math.round(lengths.content * wastedRatio);
|
|
78
78
|
|
|
79
79
|
return {
|
|
80
|
-
|
|
81
|
-
totalBytes:
|
|
80
|
+
url,
|
|
81
|
+
totalBytes: lengths.content,
|
|
82
82
|
wastedBytes,
|
|
83
83
|
wastedPercent: 100 * wastedRatio,
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* @param {WasteData} wasteData
|
|
88
|
+
* @param {WasteData[]} wasteData
|
|
89
|
+
*/
|
|
90
|
+
static determineLengths(wasteData) {
|
|
91
|
+
let unused = 0;
|
|
92
|
+
let content = 0;
|
|
93
|
+
// TODO: this is right for multiple script tags in an HTML document,
|
|
94
|
+
// but may be wrong for multiple frames using the same script resource.
|
|
95
|
+
for (const usage of wasteData) {
|
|
96
|
+
unused += usage.unusedLength;
|
|
97
|
+
content += usage.contentLength;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
content,
|
|
102
|
+
unused,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {WasteData[]} wasteData
|
|
89
108
|
* @param {LH.Artifacts.Bundle} bundle
|
|
90
109
|
*/
|
|
91
110
|
static createSourceWastedBytes(wasteData, bundle) {
|
|
@@ -112,7 +131,7 @@ class UnusedJavascriptSummary {
|
|
|
112
131
|
mapping.lastColumnNumber - 1 :
|
|
113
132
|
lineLengths[mapping.lineNumber];
|
|
114
133
|
for (let i = mapping.columnNumber; i <= lastColumnOfMapping; i++) {
|
|
115
|
-
if (wasteData.unusedByIndex[offset] === 1) {
|
|
134
|
+
if (wasteData.every(data => data.unusedByIndex[offset] === 1)) {
|
|
116
135
|
const key = mapping.sourceURL || '(unmapped)';
|
|
117
136
|
files[key] = (files[key] || 0) + 1;
|
|
118
137
|
}
|
|
@@ -136,10 +155,11 @@ class UnusedJavascriptSummary {
|
|
|
136
155
|
* @return {Promise<Summary>}
|
|
137
156
|
*/
|
|
138
157
|
static async compute_(data) {
|
|
139
|
-
const {
|
|
158
|
+
const {url, scriptCoverages, bundle} = data;
|
|
140
159
|
|
|
141
|
-
const wasteData = UnusedJavascriptSummary.computeWaste
|
|
142
|
-
const
|
|
160
|
+
const wasteData = scriptCoverages.map(UnusedJavascriptSummary.computeWaste);
|
|
161
|
+
const lengths = UnusedJavascriptSummary.determineLengths(wasteData);
|
|
162
|
+
const item = UnusedJavascriptSummary.createItem(url, lengths);
|
|
143
163
|
if (!bundle) return item;
|
|
144
164
|
|
|
145
165
|
return {
|
|
@@ -151,5 +171,5 @@ class UnusedJavascriptSummary {
|
|
|
151
171
|
|
|
152
172
|
module.exports = makeComputedArtifact(
|
|
153
173
|
UnusedJavascriptSummary,
|
|
154
|
-
['bundle', '
|
|
174
|
+
['bundle', 'scriptCoverages', 'url']
|
|
155
175
|
);
|
|
@@ -137,11 +137,11 @@ class Budget {
|
|
|
137
137
|
* If multiple budgets match based on thier 'path' property,
|
|
138
138
|
* then the last-listed of those budgets is returned.
|
|
139
139
|
* @param {Immutable<Array<LH.Budget>>|null} budgets
|
|
140
|
-
* @param {string
|
|
140
|
+
* @param {string} url
|
|
141
141
|
* @return {Immutable<LH.Budget> | undefined} budget
|
|
142
142
|
*/
|
|
143
143
|
static getMatchingBudget(budgets, url) {
|
|
144
|
-
if (budgets === null
|
|
144
|
+
if (budgets === null) return;
|
|
145
145
|
|
|
146
146
|
// Applies the LAST matching budget.
|
|
147
147
|
for (let i = budgets.length - 1; i >= 0; i--) {
|
|
@@ -41,7 +41,7 @@ const UIStrings = {
|
|
|
41
41
|
/** Description of the Accessibility category. This is displayed at the top of a list of audits focused on making web content accessible to all users. No character length limits. 'improve the accessibility of your web app' becomes link text to additional documentation. */
|
|
42
42
|
a11yCategoryDescription: 'These checks highlight opportunities to [improve the accessibility of your web app](https://web.dev/lighthouse-accessibility/). Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged.',
|
|
43
43
|
/** Description of the Accessibility manual checks category. This description is displayed above a list of accessibility audits that currently have no automated test and so must be verified manually by the user. No character length limits. 'conducting an accessibility review' becomes link text to additional documentation. */
|
|
44
|
-
a11yCategoryManualDescription: 'These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://
|
|
44
|
+
a11yCategoryManualDescription: 'These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://developers.google.com/web/fundamentals/accessibility/how-to-review).',
|
|
45
45
|
/** Title of the best practices section of the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices. */
|
|
46
46
|
a11yBestPracticesGroupTitle: 'Best practices',
|
|
47
47
|
/** Description of the best practices section within the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices. */
|
|
@@ -143,7 +143,6 @@ const defaultConfig = {
|
|
|
143
143
|
'link-elements',
|
|
144
144
|
'meta-elements',
|
|
145
145
|
'script-elements',
|
|
146
|
-
'scripts',
|
|
147
146
|
'iframe-elements',
|
|
148
147
|
'inputs',
|
|
149
148
|
'main-document-content',
|
|
@@ -13,7 +13,7 @@ const {generateFlowReportHtml} = require('../../report/generator/report-generato
|
|
|
13
13
|
const Runner = require('../runner.js');
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* @param {
|
|
16
|
+
* @param {import('puppeteer').Page} page
|
|
17
17
|
* @param {ConstructorParameters<LH.UserFlow>[1]} [options]
|
|
18
18
|
*/
|
|
19
19
|
async function startFlow(page, options) {
|
|
@@ -70,7 +70,6 @@ const artifacts = {
|
|
|
70
70
|
RobotsTxt: '',
|
|
71
71
|
ServiceWorker: '',
|
|
72
72
|
ScriptElements: '',
|
|
73
|
-
Scripts: '',
|
|
74
73
|
SourceMaps: '',
|
|
75
74
|
Stacks: '',
|
|
76
75
|
TagsBlockingFirstPaint: '',
|
|
@@ -120,7 +119,6 @@ const defaultConfig = {
|
|
|
120
119
|
{id: artifacts.RobotsTxt, gatherer: 'seo/robots-txt'},
|
|
121
120
|
{id: artifacts.ServiceWorker, gatherer: 'service-worker'},
|
|
122
121
|
{id: artifacts.ScriptElements, gatherer: 'script-elements'},
|
|
123
|
-
{id: artifacts.Scripts, gatherer: 'scripts'},
|
|
124
122
|
{id: artifacts.SourceMaps, gatherer: 'source-maps'},
|
|
125
123
|
{id: artifacts.Stacks, gatherer: 'stacks'},
|
|
126
124
|
{id: artifacts.TagsBlockingFirstPaint, gatherer: 'dobetterweb/tags-blocking-first-paint'},
|
|
@@ -175,7 +173,6 @@ const defaultConfig = {
|
|
|
175
173
|
artifacts.RobotsTxt,
|
|
176
174
|
artifacts.ServiceWorker,
|
|
177
175
|
artifacts.ScriptElements,
|
|
178
|
-
artifacts.Scripts,
|
|
179
176
|
artifacts.SourceMaps,
|
|
180
177
|
artifacts.Stacks,
|
|
181
178
|
artifacts.TagsBlockingFirstPaint,
|
|
@@ -35,10 +35,7 @@ async function getBaseArtifacts(config, driver, context) {
|
|
|
35
35
|
HostFormFactor: userAgent.includes('Android') || userAgent.includes('Mobile') ?
|
|
36
36
|
'mobile' : 'desktop',
|
|
37
37
|
// Contextual artifacts whose collection changes based on gather mode.
|
|
38
|
-
URL: {
|
|
39
|
-
initialUrl: '',
|
|
40
|
-
finalUrl: '',
|
|
41
|
-
},
|
|
38
|
+
URL: {requestedUrl: '', finalUrl: ''},
|
|
42
39
|
PageLoadError: null,
|
|
43
40
|
GatherContext: context,
|
|
44
41
|
// Artifacts that have been replaced by regular gatherers in Fraggle Rock.
|
|
@@ -86,11 +83,11 @@ function finalizeArtifacts(baseArtifacts, gathererArtifacts) {
|
|
|
86
83
|
artifacts.LighthouseRunWarnings = deduplicateWarnings(warnings);
|
|
87
84
|
|
|
88
85
|
if (artifacts.PageLoadError && !artifacts.URL.finalUrl) {
|
|
89
|
-
artifacts.URL.finalUrl = artifacts.URL.requestedUrl
|
|
86
|
+
artifacts.URL.finalUrl = artifacts.URL.requestedUrl;
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
// Check that the runner remembered to mutate the special-case URL artifact.
|
|
93
|
-
if (!artifacts.URL.
|
|
90
|
+
if (!artifacts.URL.requestedUrl) throw new Error('Runner did not set requestedUrl');
|
|
94
91
|
if (!artifacts.URL.finalUrl) throw new Error('Runner did not set finalUrl');
|
|
95
92
|
|
|
96
93
|
return artifacts;
|
|
@@ -35,7 +35,7 @@ const defaultSession = {
|
|
|
35
35
|
/** @implements {LH.Gatherer.FRTransitionalDriver} */
|
|
36
36
|
class Driver {
|
|
37
37
|
/**
|
|
38
|
-
* @param {
|
|
38
|
+
* @param {import('puppeteer').Page} page
|
|
39
39
|
*/
|
|
40
40
|
constructor(page) {
|
|
41
41
|
this._page = page;
|
|
@@ -74,7 +74,7 @@ class Driver {
|
|
|
74
74
|
const session = await this._page.target().createCDPSession();
|
|
75
75
|
this._session = this.defaultSession = new ProtocolSession(session);
|
|
76
76
|
this._executionContext = new ExecutionContext(this._session);
|
|
77
|
-
this._fetcher = new Fetcher(this._session);
|
|
77
|
+
this._fetcher = new Fetcher(this._session, this._executionContext);
|
|
78
78
|
log.timeEnd(status);
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const puppeteer = require('puppeteer-core');
|
|
9
8
|
const log = require('lighthouse-logger');
|
|
10
9
|
const Driver = require('./driver.js');
|
|
11
10
|
const Runner = require('../../runner.js');
|
|
@@ -44,20 +43,18 @@ const NetworkRecords = require('../../computed/network-records.js');
|
|
|
44
43
|
|
|
45
44
|
/** @typedef {Omit<Parameters<typeof collectPhaseArtifacts>[0], 'phase'>} PhaseState */
|
|
46
45
|
|
|
47
|
-
const DEFAULT_HOSTNAME = '127.0.0.1';
|
|
48
|
-
const DEFAULT_PORT = 9222;
|
|
49
|
-
|
|
50
46
|
/**
|
|
51
|
-
* @param {{driver: Driver, config: LH.Config.FRConfig, options?: InternalOptions}} args
|
|
47
|
+
* @param {{driver: Driver, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor, options?: InternalOptions}} args
|
|
52
48
|
* @return {Promise<{baseArtifacts: LH.FRBaseArtifacts}>}
|
|
53
49
|
*/
|
|
54
|
-
async function _setup({driver, config, options}) {
|
|
50
|
+
async function _setup({driver, config, requestor, options}) {
|
|
55
51
|
await driver.connect();
|
|
56
52
|
if (!options?.skipAboutBlank) {
|
|
57
53
|
await gotoURL(driver, defaultNavigationConfig.blankPage, {waitUntil: ['navigated']});
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'navigation'});
|
|
57
|
+
if (typeof requestor === 'string') baseArtifacts.URL.requestedUrl = requestor;
|
|
61
58
|
|
|
62
59
|
await prepare.prepareTargetForNavigationMode(driver, config.settings);
|
|
63
60
|
|
|
@@ -93,32 +90,25 @@ async function _cleanupNavigation({driver}) {
|
|
|
93
90
|
|
|
94
91
|
/**
|
|
95
92
|
* @param {NavigationContext} navigationContext
|
|
96
|
-
* @return {Promise<{requestedUrl: string,
|
|
93
|
+
* @return {Promise<{requestedUrl: string, finalUrl: string, navigationError: LH.LighthouseError | undefined, warnings: Array<LH.IcuMessage>}>}
|
|
97
94
|
*/
|
|
98
95
|
async function _navigate(navigationContext) {
|
|
99
96
|
const {driver, config, requestor} = navigationContext;
|
|
100
97
|
|
|
101
98
|
try {
|
|
102
|
-
const {requestedUrl,
|
|
99
|
+
const {requestedUrl, finalUrl, warnings} = await gotoURL(driver, requestor, {
|
|
103
100
|
...navigationContext.navigation,
|
|
104
101
|
debugNavigation: config.settings.debugNavigation,
|
|
105
102
|
maxWaitForFcp: config.settings.maxWaitForFcp,
|
|
106
103
|
maxWaitForLoad: config.settings.maxWaitForLoad,
|
|
107
104
|
waitUntil: navigationContext.navigation.pauseAfterFcpMs ? ['fcp', 'load'] : ['load'],
|
|
108
105
|
});
|
|
109
|
-
return {requestedUrl,
|
|
106
|
+
return {requestedUrl, finalUrl, navigationError: undefined, warnings};
|
|
110
107
|
} catch (err) {
|
|
111
108
|
if (!(err instanceof LighthouseError)) throw err;
|
|
112
109
|
if (err.code !== 'NO_FCP' && err.code !== 'PAGE_HUNG') throw err;
|
|
113
110
|
if (typeof requestor !== 'string') throw err;
|
|
114
|
-
|
|
115
|
-
// TODO: Make the urls optional here so we don't need to throw an error with a callback requestor.
|
|
116
|
-
return {
|
|
117
|
-
requestedUrl: requestor,
|
|
118
|
-
mainDocumentUrl: requestor,
|
|
119
|
-
navigationError: err,
|
|
120
|
-
warnings: [],
|
|
121
|
-
};
|
|
111
|
+
return {requestedUrl: requestor, finalUrl: requestor, navigationError: err, warnings: []};
|
|
122
112
|
}
|
|
123
113
|
}
|
|
124
114
|
|
|
@@ -162,7 +152,7 @@ async function _collectDebugData(navigationContext, phaseState) {
|
|
|
162
152
|
* @param {PhaseState} phaseState
|
|
163
153
|
* @param {Awaited<ReturnType<typeof _setupNavigation>>} setupResult
|
|
164
154
|
* @param {Awaited<ReturnType<typeof _navigate>>} navigateResult
|
|
165
|
-
* @return {Promise<{artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
|
|
155
|
+
* @return {Promise<{requestedUrl: string, finalUrl: string, artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
|
|
166
156
|
*/
|
|
167
157
|
async function _computeNavigationResult(
|
|
168
158
|
navigationContext,
|
|
@@ -170,12 +160,12 @@ async function _computeNavigationResult(
|
|
|
170
160
|
setupResult,
|
|
171
161
|
navigateResult
|
|
172
162
|
) {
|
|
173
|
-
const {navigationError,
|
|
163
|
+
const {navigationError, finalUrl} = navigateResult;
|
|
174
164
|
const warnings = [...setupResult.warnings, ...navigateResult.warnings];
|
|
175
165
|
const debugData = await _collectDebugData(navigationContext, phaseState);
|
|
176
166
|
const pageLoadError = debugData.records
|
|
177
167
|
? getPageLoadError(navigationError, {
|
|
178
|
-
url:
|
|
168
|
+
url: finalUrl,
|
|
179
169
|
loadFailureMode: navigationContext.navigation.loadFailureMode,
|
|
180
170
|
networkRecords: debugData.records,
|
|
181
171
|
})
|
|
@@ -193,6 +183,8 @@ async function _computeNavigationResult(
|
|
|
193
183
|
if (debugData.trace) artifacts.traces = {[pageLoadErrorId]: debugData.trace};
|
|
194
184
|
|
|
195
185
|
return {
|
|
186
|
+
requestedUrl: navigateResult.requestedUrl,
|
|
187
|
+
finalUrl,
|
|
196
188
|
pageLoadError,
|
|
197
189
|
artifacts,
|
|
198
190
|
warnings: [...warnings, pageLoadError.friendlyMessage],
|
|
@@ -202,6 +194,8 @@ async function _computeNavigationResult(
|
|
|
202
194
|
|
|
203
195
|
const artifacts = await awaitArtifacts(phaseState.artifactState);
|
|
204
196
|
return {
|
|
197
|
+
requestedUrl: navigateResult.requestedUrl,
|
|
198
|
+
finalUrl,
|
|
205
199
|
artifacts,
|
|
206
200
|
warnings,
|
|
207
201
|
pageLoadError: undefined,
|
|
@@ -215,9 +209,8 @@ async function _computeNavigationResult(
|
|
|
215
209
|
*/
|
|
216
210
|
async function _navigation(navigationContext) {
|
|
217
211
|
const artifactState = getEmptyArtifactState();
|
|
218
|
-
const initialUrl = await navigationContext.driver.url();
|
|
219
212
|
const phaseState = {
|
|
220
|
-
url:
|
|
213
|
+
url: await navigationContext.driver.url(),
|
|
221
214
|
gatherMode: /** @type {const} */ ('navigation'),
|
|
222
215
|
driver: navigationContext.driver,
|
|
223
216
|
computedCache: navigationContext.computedCache,
|
|
@@ -231,19 +224,7 @@ async function _navigation(navigationContext) {
|
|
|
231
224
|
await collectPhaseArtifacts({phase: 'startInstrumentation', ...phaseState});
|
|
232
225
|
await collectPhaseArtifacts({phase: 'startSensitiveInstrumentation', ...phaseState});
|
|
233
226
|
const navigateResult = await _navigate(navigationContext);
|
|
234
|
-
|
|
235
|
-
// Every required url is initialized to an empty string in `getBaseArtifacts`.
|
|
236
|
-
// If we haven't set all the required urls yet, set them here.
|
|
237
|
-
if (!Object.values(phaseState.baseArtifacts).every(Boolean)) {
|
|
238
|
-
phaseState.baseArtifacts.URL = {
|
|
239
|
-
initialUrl,
|
|
240
|
-
requestedUrl: navigateResult.requestedUrl,
|
|
241
|
-
mainDocumentUrl: navigateResult.mainDocumentUrl,
|
|
242
|
-
finalUrl: navigateResult.mainDocumentUrl,
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
phaseState.url = navigateResult.mainDocumentUrl;
|
|
246
|
-
|
|
227
|
+
phaseState.url = navigateResult.finalUrl;
|
|
247
228
|
await collectPhaseArtifacts({phase: 'stopSensitiveInstrumentation', ...phaseState});
|
|
248
229
|
await collectPhaseArtifacts({phase: 'stopInstrumentation', ...phaseState});
|
|
249
230
|
await _cleanupNavigation(navigationContext);
|
|
@@ -281,6 +262,11 @@ async function _navigations({driver, config, requestor, baseArtifacts, computedC
|
|
|
281
262
|
artifacts.PageLoadError = navigationResult.pageLoadError;
|
|
282
263
|
shouldHaltNavigations = true;
|
|
283
264
|
}
|
|
265
|
+
|
|
266
|
+
artifacts.URL = {
|
|
267
|
+
requestedUrl: navigationResult.requestedUrl,
|
|
268
|
+
finalUrl: navigationResult.finalUrl,
|
|
269
|
+
};
|
|
284
270
|
}
|
|
285
271
|
|
|
286
272
|
LighthouseRunWarnings.push(...navigationResult.warnings);
|
|
@@ -302,12 +288,12 @@ async function _cleanup({requestedUrl, driver, config}) {
|
|
|
302
288
|
}
|
|
303
289
|
|
|
304
290
|
/**
|
|
305
|
-
* @param {LH.NavigationRequestor
|
|
306
|
-
* @param {{page
|
|
291
|
+
* @param {LH.NavigationRequestor} requestor
|
|
292
|
+
* @param {{page: import('puppeteer').Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
|
|
307
293
|
* @return {Promise<LH.Gatherer.FRGatherResult>}
|
|
308
294
|
*/
|
|
309
295
|
async function navigationGather(requestor, options) {
|
|
310
|
-
const {configContext = {}} = options;
|
|
296
|
+
const {page, configContext = {}} = options;
|
|
311
297
|
log.setLevel(configContext.logLevel || 'error');
|
|
312
298
|
|
|
313
299
|
const {config} = initializeConfig(options.config, {...configContext, gatherMode: 'navigation'});
|
|
@@ -317,29 +303,18 @@ async function navigationGather(requestor, options) {
|
|
|
317
303
|
};
|
|
318
304
|
|
|
319
305
|
// We can't trigger the navigation through user interaction if we reset the page before starting.
|
|
320
|
-
|
|
321
|
-
if (isCallback) {
|
|
306
|
+
if (typeof requestor !== 'string') {
|
|
322
307
|
internalOptions.skipAboutBlank = true;
|
|
323
308
|
}
|
|
324
309
|
|
|
325
310
|
const runnerOptions = {config, computedCache};
|
|
326
311
|
const artifacts = await Runner.gather(
|
|
327
312
|
async () => {
|
|
328
|
-
let {page} = options;
|
|
329
|
-
|
|
330
|
-
// For navigation mode, we shouldn't connect to a browser in audit mode,
|
|
331
|
-
// therefore we connect to the browser in the gatherFn callback.
|
|
332
|
-
if (!page) {
|
|
333
|
-
const {hostname = DEFAULT_HOSTNAME, port = DEFAULT_PORT} = configContext;
|
|
334
|
-
const browser = await puppeteer.connect({browserURL: `http://${hostname}:${port}`});
|
|
335
|
-
page = await browser.newPage();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
313
|
const driver = new Driver(page);
|
|
339
314
|
const context = {
|
|
340
315
|
driver,
|
|
341
316
|
config,
|
|
342
|
-
requestor:
|
|
317
|
+
requestor: typeof requestor === 'string' ? URL.normalizeUrl(requestor) : requestor,
|
|
343
318
|
options: internalOptions,
|
|
344
319
|
};
|
|
345
320
|
const {baseArtifacts} = await _setup(context);
|
|
@@ -15,6 +15,7 @@
|
|
|
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
|
|
18
19
|
*/
|
|
19
20
|
|
|
20
21
|
/** @typedef {Record<string, Promise<any>>} IntermediateArtifacts */
|
|
@@ -74,6 +75,7 @@ async function collectPhaseArtifacts(options) {
|
|
|
74
75
|
gatherMode,
|
|
75
76
|
computedCache,
|
|
76
77
|
settings,
|
|
78
|
+
url,
|
|
77
79
|
} = options;
|
|
78
80
|
const priorPhase = phaseToPriorPhase[phase];
|
|
79
81
|
const priorPhaseArtifacts = (priorPhase && artifactState[priorPhase]) || {};
|
|
@@ -90,6 +92,7 @@ async function collectPhaseArtifacts(options) {
|
|
|
90
92
|
: /** @type {Dependencies} */ ({});
|
|
91
93
|
|
|
92
94
|
return gatherer[phase]({
|
|
95
|
+
url,
|
|
93
96
|
gatherMode,
|
|
94
97
|
driver,
|
|
95
98
|
baseArtifacts,
|