lighthouse 9.5.0-dev.20220906 → 9.5.0-dev.20220908
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/cli/cli-flags.js +17 -0
- package/cli/run.js +2 -2
- package/cli/test/smokehouse/core-tests.js +2 -3
- package/cli/test/smokehouse/report-assert.js +0 -4
- package/cli/test/smokehouse/smokehouse.js +6 -0
- package/core/audits/bootup-time.js +2 -2
- package/core/audits/byte-efficiency/byte-efficiency-audit.js +7 -6
- package/core/audits/byte-efficiency/duplicated-javascript.js +1 -1
- package/core/audits/byte-efficiency/legacy-javascript.js +2 -2
- package/core/audits/byte-efficiency/modern-image-formats.js +5 -5
- package/core/audits/byte-efficiency/offscreen-images.js +4 -4
- package/core/audits/byte-efficiency/render-blocking-resources.js +5 -5
- package/core/audits/byte-efficiency/total-byte-weight.js +1 -1
- package/core/audits/byte-efficiency/unminified-css.js +1 -1
- package/core/audits/byte-efficiency/unused-css-rules.js +1 -1
- package/core/audits/byte-efficiency/unused-javascript.js +4 -4
- package/core/audits/byte-efficiency/uses-long-cache-ttl.js +3 -3
- package/core/audits/byte-efficiency/uses-optimized-images.js +5 -5
- package/core/audits/byte-efficiency/uses-responsive-images-snapshot.js +2 -2
- package/core/audits/byte-efficiency/uses-responsive-images.js +3 -3
- package/core/audits/byte-efficiency/uses-text-compression.js +2 -2
- package/core/audits/critical-request-chains.js +1 -1
- package/core/audits/csp-xss.js +1 -1
- package/core/audits/deprecations.js +2 -2
- package/core/audits/diagnostics.js +7 -7
- package/core/audits/dobetterweb/charset.js +1 -1
- package/core/audits/dobetterweb/uses-http2.js +8 -8
- package/core/audits/errors-in-console.js +2 -2
- package/core/audits/final-screenshot.js +2 -2
- package/core/audits/font-display.js +7 -6
- package/core/audits/image-aspect-ratio.js +3 -3
- package/core/audits/image-size-responsive.js +3 -3
- package/core/audits/installable-manifest.js +1 -1
- package/core/audits/is-on-https.js +3 -3
- package/core/audits/long-tasks.js +4 -4
- package/core/audits/main-thread-tasks.js +1 -1
- package/core/audits/mainthread-work-breakdown.js +1 -1
- package/core/audits/maskable-icon.js +1 -1
- package/core/audits/metrics/cumulative-layout-shift.js +1 -1
- package/core/audits/metrics/experimental-interaction-to-next-paint.js +1 -1
- package/core/audits/metrics/first-contentful-paint-3g.js +1 -1
- package/core/audits/metrics/first-contentful-paint.js +1 -1
- package/core/audits/metrics/first-meaningful-paint.js +1 -1
- package/core/audits/metrics/interactive.js +1 -1
- package/core/audits/metrics/largest-contentful-paint.js +1 -1
- package/core/audits/metrics/max-potential-fid.js +1 -1
- package/core/audits/metrics/speed-index.js +1 -1
- package/core/audits/metrics/total-blocking-time.js +1 -1
- package/core/audits/metrics.js +2 -2
- package/core/audits/network-requests.js +4 -4
- package/core/audits/network-rtt.js +3 -3
- package/core/audits/network-server-latency.js +3 -3
- package/core/audits/no-unload-listeners.js +2 -2
- package/core/audits/performance-budget.js +2 -2
- package/core/audits/predictive-perf.js +8 -8
- package/core/audits/preload-fonts.js +1 -1
- package/core/audits/preload-lcp-image.js +4 -4
- package/core/audits/redirects.js +4 -4
- package/core/audits/resource-summary.js +1 -1
- package/core/audits/screenshot-thumbnails.js +1 -1
- package/core/audits/script-treemap-data.js +5 -5
- package/core/audits/seo/canonical.js +3 -3
- package/core/audits/seo/font-size.js +2 -2
- package/core/audits/seo/http-status-code.js +1 -1
- package/core/audits/seo/is-crawlable.js +1 -2
- package/core/audits/seo/link-text.js +2 -2
- package/core/audits/seo/plugins.js +0 -1
- package/core/audits/seo/robots-txt.js +0 -1
- package/core/audits/seo/tap-targets.js +2 -2
- package/core/audits/server-response-time.js +1 -1
- package/core/audits/service-worker.js +0 -1
- package/core/audits/splash-screen.js +1 -1
- package/core/audits/themed-omnibox.js +1 -1
- package/core/audits/third-party-facades.js +3 -3
- package/core/audits/third-party-summary.js +2 -2
- package/core/audits/timing-budget.js +2 -2
- package/core/audits/unsized-images.js +4 -4
- package/core/audits/user-timings.js +1 -1
- package/core/audits/uses-rel-preconnect.js +12 -10
- package/core/audits/uses-rel-preload.js +6 -6
- package/core/audits/viewport.js +2 -2
- package/core/audits/violation-audit.js +2 -2
- package/core/audits/work-during-interaction.js +4 -4
- package/core/computed/critical-request-chains.js +5 -3
- package/core/computed/image-records.js +5 -3
- package/core/computed/js-bundles.js +2 -1
- package/core/computed/load-simulator.js +3 -5
- package/core/computed/main-resource.js +3 -2
- package/core/computed/main-thread-tasks.js +3 -2
- package/core/computed/manifest-values.js +3 -1
- package/core/computed/metrics/cumulative-layout-shift.js +3 -2
- package/core/computed/metrics/first-contentful-paint-all-frames.js +3 -2
- package/core/computed/metrics/first-contentful-paint.js +4 -3
- package/core/computed/metrics/first-meaningful-paint.js +4 -3
- package/core/computed/metrics/interactive.js +4 -3
- package/core/computed/metrics/lantern-first-contentful-paint.js +3 -2
- package/core/computed/metrics/lantern-first-meaningful-paint.js +4 -3
- package/core/computed/metrics/lantern-interactive.js +4 -3
- package/core/computed/metrics/lantern-largest-contentful-paint.js +4 -3
- package/core/computed/metrics/lantern-max-potential-fid.js +5 -4
- package/core/computed/metrics/lantern-metric.js +6 -6
- package/core/computed/metrics/lantern-speed-index.js +5 -4
- package/core/computed/metrics/lantern-total-blocking-time.js +5 -4
- package/core/computed/metrics/largest-contentful-paint-all-frames.js +3 -2
- package/core/computed/metrics/largest-contentful-paint.js +4 -3
- package/core/computed/metrics/max-potential-fid.js +4 -3
- package/core/computed/metrics/metric.js +3 -3
- package/core/computed/metrics/navigation-metric.js +4 -3
- package/core/computed/metrics/responsiveness.js +3 -2
- package/core/computed/metrics/speed-index.js +5 -4
- package/core/computed/metrics/timing-summary.js +15 -14
- package/core/computed/metrics/total-blocking-time.js +5 -4
- package/core/computed/module-duplication.js +5 -3
- package/core/computed/network-analysis.js +3 -2
- package/core/computed/network-records.js +2 -1
- package/core/computed/page-dependency-graph.js +13 -11
- package/core/computed/processed-navigation.js +2 -1
- package/core/computed/processed-trace.js +2 -1
- package/core/computed/resource-summary.js +4 -3
- package/core/computed/screenshots.js +2 -1
- package/core/computed/speedline.js +3 -2
- package/core/computed/unused-css.js +3 -2
- package/core/computed/unused-javascript-summary.js +2 -1
- package/core/computed/user-timings.js +3 -2
- package/core/computed/viewport-meta.js +2 -1
- package/core/fraggle-rock/gather/navigation-runner.js +3 -3
- package/core/gather/driver/navigation.js +3 -3
- package/core/gather/driver/network-monitor.js +2 -2
- package/core/gather/gather-runner.js +3 -3
- package/core/gather/gatherers/dobetterweb/optimized-images.js +3 -3
- package/core/gather/gatherers/dobetterweb/response-compression.js +3 -3
- package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +1 -1
- package/core/gather/gatherers/inspector-issues.js +1 -1
- package/core/gather/gatherers/link-elements.js +1 -2
- package/core/gather/gatherers/main-document-content.js +1 -1
- package/core/gather/gatherers/script-elements.js +1 -1
- package/core/gather/gatherers/source-maps.js +0 -1
- package/core/gather/gatherers/trace-elements.js +4 -4
- package/core/index.js +3 -3
- package/core/lib/asset-saver.js +4 -4
- package/core/lib/dependency-graph/simulator/network-analyzer.js +2 -2
- package/core/lib/icons.js +0 -2
- package/core/lib/manifest-parser.js +0 -2
- package/core/lib/network-request.js +7 -7
- package/core/lib/{url-shim.js → url-utils.js} +4 -12
- package/package.json +2 -3
- package/report/test/renderer/performance-category-renderer-test.js +0 -1
- package/report/test/renderer/report-renderer-test.js +0 -1
- package/tsconfig.json +1 -1
- package/core/fraggle-rock/replay/stringify-extension.js +0 -104
package/cli/cli-flags.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
/* eslint-disable max-len */
|
|
8
8
|
|
|
9
9
|
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
10
11
|
|
|
11
12
|
import yargs from 'yargs';
|
|
12
13
|
import * as yargsHelpers from 'yargs/helpers';
|
|
@@ -227,6 +228,7 @@ function getYargsParser(manualArgv) {
|
|
|
227
228
|
},
|
|
228
229
|
'output-path': {
|
|
229
230
|
type: 'string',
|
|
231
|
+
coerce: coerceOutputPath,
|
|
230
232
|
describe: `The file path to output the results. Use 'stdout' to write to stdout.
|
|
231
233
|
If using JSON output, default is stdout.
|
|
232
234
|
If using HTML or CSV output, default is a file in the working directory with a name based on the test URL and date.
|
|
@@ -408,6 +410,21 @@ function coerceOutput(values) {
|
|
|
408
410
|
return validValues;
|
|
409
411
|
}
|
|
410
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Verifies outputPath is something we can actually write to.
|
|
415
|
+
* @param {unknown=} value
|
|
416
|
+
* @return {string=}
|
|
417
|
+
*/
|
|
418
|
+
function coerceOutputPath(value) {
|
|
419
|
+
if (value === undefined) return;
|
|
420
|
+
|
|
421
|
+
if (typeof value !== 'string' || !value || !fs.existsSync(path.dirname(value))) {
|
|
422
|
+
throw new Error(`--output-path (${value}) cannot be written to`);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return value;
|
|
426
|
+
}
|
|
427
|
+
|
|
411
428
|
/**
|
|
412
429
|
* Verifies value is a string, then coerces type to LH.Locale for convenience. However, don't
|
|
413
430
|
* allowlist specific locales. Why? So we can support the user who requests 'es-MX' (unsupported)
|
package/cli/run.js
CHANGED
|
@@ -19,7 +19,7 @@ import * as Printer from './printer.js';
|
|
|
19
19
|
import lighthouse, {legacyNavigation} from '../core/index.js';
|
|
20
20
|
import {getLhrFilenamePrefix} from '../report/generator/file-namer.js';
|
|
21
21
|
import * as assetSaver from '../core/lib/asset-saver.js';
|
|
22
|
-
import
|
|
22
|
+
import UrlUtils from '../core/lib/url-utils.js';
|
|
23
23
|
|
|
24
24
|
/** @typedef {Error & {code: string, friendlyMessage?: string}} ExitError */
|
|
25
25
|
|
|
@@ -232,7 +232,7 @@ async function runLighthouse(url, flags, config) {
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
const shouldGather = flags.gatherMode || flags.gatherMode === flags.auditMode;
|
|
235
|
-
const shouldUseLocalChrome =
|
|
235
|
+
const shouldUseLocalChrome = UrlUtils.isLikeLocalhost(flags.hostname);
|
|
236
236
|
if (shouldGather && shouldUseLocalChrome) {
|
|
237
237
|
launchedChrome = await getDebuggableChrome(flags);
|
|
238
238
|
flags.port = launchedChrome.port;
|
|
@@ -42,7 +42,7 @@ import perfFonts from './test-definitions/perf-fonts.js';
|
|
|
42
42
|
import perfFrameMetrics from './test-definitions/perf-frame-metrics.js';
|
|
43
43
|
import perfPreload from './test-definitions/perf-preload.js';
|
|
44
44
|
import perfTraceElements from './test-definitions/perf-trace-elements.js';
|
|
45
|
-
|
|
45
|
+
import pubads from './test-definitions/pubads.js';
|
|
46
46
|
import pwaAirhorner from './test-definitions/pwa-airhorner.js';
|
|
47
47
|
import pwaCaltrain from './test-definitions/pwa-caltrain.js';
|
|
48
48
|
import pwaChromestatus from './test-definitions/pwa-chromestatus.js';
|
|
@@ -103,8 +103,7 @@ const smokeTests = [
|
|
|
103
103
|
perfFrameMetrics,
|
|
104
104
|
perfPreload,
|
|
105
105
|
perfTraceElements,
|
|
106
|
-
|
|
107
|
-
// pubads,
|
|
106
|
+
pubads,
|
|
108
107
|
pwaAirhorner,
|
|
109
108
|
pwaChromestatus,
|
|
110
109
|
pwaSvgomg,
|
|
@@ -259,10 +259,6 @@ function pruneExpectations(localConsole, lhr, expected, reportOptions) {
|
|
|
259
259
|
* @param {*} obj
|
|
260
260
|
*/
|
|
261
261
|
function failsChromeVersionCheck(obj) {
|
|
262
|
-
// LHR never actually run, so we can't know. Better to not prune
|
|
263
|
-
// things than to fail loudly when accessing lhr.environment.
|
|
264
|
-
if (!lhr.environment) return false;
|
|
265
|
-
|
|
266
262
|
return !chromiumVersionCheck({
|
|
267
263
|
version: getChromeVersionString(),
|
|
268
264
|
min: obj._minChromiumVersion,
|
|
@@ -195,6 +195,12 @@ async function runSmokeTest(smokeTestDefn, testOptions) {
|
|
|
195
195
|
...await lighthouseRunner(requestedUrl, configJson, {isDebug, useLegacyNavigation}),
|
|
196
196
|
networkRequests: takeNetworkRequestUrls ? takeNetworkRequestUrls() : undefined,
|
|
197
197
|
};
|
|
198
|
+
|
|
199
|
+
if (!result.lhr?.audits || !result.artifacts) {
|
|
200
|
+
// Something went really wrong and the runner didn't catch it.
|
|
201
|
+
throw new Error('lighthouse runner returned a bad result. got lhr:\n' +
|
|
202
|
+
JSON.stringify(result.lhr, null, 2));
|
|
203
|
+
}
|
|
198
204
|
} catch (e) {
|
|
199
205
|
// Clear the network requests so that when we retry, we don't see duplicates.
|
|
200
206
|
if (takeNetworkRequestUrls) takeNetworkRequestUrls();
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import {Audit} from './audit.js';
|
|
8
8
|
import {taskGroups} from '../lib/tracehouse/task-groups.js';
|
|
9
9
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
10
|
-
import NetworkRecords from '../computed/network-records.js';
|
|
11
|
-
import MainThreadTasks from '../computed/main-thread-tasks.js';
|
|
10
|
+
import {NetworkRecords} from '../computed/network-records.js';
|
|
11
|
+
import {MainThreadTasks} from '../computed/main-thread-tasks.js';
|
|
12
12
|
import {getExecutionTimingsByURL} from '../lib/tracehouse/task-summary.js';
|
|
13
13
|
|
|
14
14
|
const UIStrings = {
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import {Audit} from '../audit.js';
|
|
8
8
|
import {linearInterpolation} from '../../lib/statistics.js';
|
|
9
|
-
import
|
|
9
|
+
import {LanternInteractive} from '../../computed/metrics/lantern-interactive.js';
|
|
10
10
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
-
import NetworkRecords from '../../computed/network-records.js';
|
|
12
|
-
import LoadSimulator from '../../computed/load-simulator.js';
|
|
13
|
-
import PageDependencyGraph from '../../computed/page-dependency-graph.js';
|
|
11
|
+
import {NetworkRecords} from '../../computed/network-records.js';
|
|
12
|
+
import {LoadSimulator} from '../../computed/load-simulator.js';
|
|
13
|
+
import {PageDependencyGraph} from '../../computed/page-dependency-graph.js';
|
|
14
14
|
|
|
15
15
|
const str_ = i18n.createIcuMessageFn(import.meta.url, {});
|
|
16
16
|
|
|
@@ -190,8 +190,9 @@ class ByteEfficiencyAudit extends Audit {
|
|
|
190
190
|
});
|
|
191
191
|
|
|
192
192
|
const savingsOnOverallLoad = simulationBeforeChanges.timeInMs - simulationAfterChanges.timeInMs;
|
|
193
|
-
const savingsOnTTI =
|
|
194
|
-
|
|
193
|
+
const savingsOnTTI =
|
|
194
|
+
LanternInteractive.getLastLongTaskEndTime(simulationBeforeChanges.nodeTimings) -
|
|
195
|
+
LanternInteractive.getLastLongTaskEndTime(simulationAfterChanges.nodeTimings);
|
|
195
196
|
|
|
196
197
|
let savings = savingsOnTTI;
|
|
197
198
|
if (options.includeLoad) savings = Math.max(savings, savingsOnOverallLoad);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
/** @typedef {{url: string, sourceTransferBytes?: number}} SubItem */
|
|
10
10
|
|
|
11
11
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
12
|
-
import ModuleDuplication from '../../computed/module-duplication.js';
|
|
12
|
+
import {ModuleDuplication} from '../../computed/module-duplication.js';
|
|
13
13
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
14
14
|
import {getRequestForScript} from '../../lib/script-helpers.js';
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import fs from 'fs';
|
|
21
21
|
|
|
22
22
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
23
|
-
import
|
|
23
|
+
import {JSBundles} from '../../computed/js-bundles.js';
|
|
24
24
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
25
25
|
import thirdPartyWeb from '../../lib/third-party-web.js';
|
|
26
26
|
import {getRequestForScript} from '../../lib/script-helpers.js';
|
|
@@ -402,7 +402,7 @@ class LegacyJavascript extends ByteEfficiencyAudit {
|
|
|
402
402
|
*/
|
|
403
403
|
static async audit_(artifacts, networkRecords, context) {
|
|
404
404
|
const mainDocumentEntity = thirdPartyWeb.getEntity(artifacts.URL.finalUrl);
|
|
405
|
-
const bundles = await
|
|
405
|
+
const bundles = await JSBundles.request(artifacts, context);
|
|
406
406
|
|
|
407
407
|
/** @type {Item[]} */
|
|
408
408
|
const items = [];
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
12
|
-
import
|
|
12
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
13
13
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
14
14
|
|
|
15
15
|
const UIStrings = {
|
|
@@ -106,7 +106,7 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
106
106
|
const imageElement = imageElementsByURL.get(image.url);
|
|
107
107
|
|
|
108
108
|
if (image.failed) {
|
|
109
|
-
warnings.push(`Unable to decode ${
|
|
109
|
+
warnings.push(`Unable to decode ${UrlUtils.getURLDisplayName(image.url)}`);
|
|
110
110
|
continue;
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -123,7 +123,7 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
123
123
|
|
|
124
124
|
if (typeof webpSize === 'undefined') {
|
|
125
125
|
if (!imageElement) {
|
|
126
|
-
warnings.push(`Unable to locate resource ${
|
|
126
|
+
warnings.push(`Unable to locate resource ${UrlUtils.getURLDisplayName(image.url)}`);
|
|
127
127
|
continue;
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -152,8 +152,8 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
152
152
|
const wastedBytes = image.originalSize - avifSize;
|
|
153
153
|
if (wastedBytes < IGNORE_THRESHOLD_IN_BYTES) continue;
|
|
154
154
|
|
|
155
|
-
const url =
|
|
156
|
-
const isCrossOrigin = !
|
|
155
|
+
const url = UrlUtils.elideDataURI(image.url);
|
|
156
|
+
const isCrossOrigin = !UrlUtils.originsMatch(pageURL, image.url);
|
|
157
157
|
|
|
158
158
|
items.push({
|
|
159
159
|
node: imageElement ? ByteEfficiencyAudit.makeNodeItem(imageElement.node) : undefined,
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
13
13
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
14
14
|
import {Sentry} from '../../lib/sentry.js';
|
|
15
|
-
import
|
|
15
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
16
16
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
17
|
-
import Interactive from '../../computed/metrics/interactive.js';
|
|
18
|
-
import ProcessedTrace from '../../computed/processed-trace.js';
|
|
17
|
+
import {Interactive} from '../../computed/metrics/interactive.js';
|
|
18
|
+
import {ProcessedTrace} from '../../computed/processed-trace.js';
|
|
19
19
|
|
|
20
20
|
const UIStrings = {
|
|
21
21
|
/** Imperative title of a Lighthouse audit that tells the user to defer loading offscreen images. Offscreen images are images located outside of the visible browser viewport. As they are unseen by the user and slow down page load, they should be loaded later, closer to when the user is going to see them. This is displayed in a list of audit titles that Lighthouse generates. */
|
|
@@ -87,7 +87,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
87
87
|
// If the image had its loading behavior explicitly controlled already, treat it as passed.
|
|
88
88
|
if (image.loading === 'lazy' || image.loading === 'eager') return null;
|
|
89
89
|
|
|
90
|
-
const url =
|
|
90
|
+
const url = UrlUtils.elideDataURI(image.src);
|
|
91
91
|
const totalPixels = image.displayedWidth * image.displayedHeight;
|
|
92
92
|
const visiblePixels = this.computeVisiblePixels(image.clientRect, viewportDimensions);
|
|
93
93
|
// Treat images with 0 area as if they're offscreen. See https://github.com/GoogleChrome/lighthouse/issues/1914
|
|
@@ -13,12 +13,12 @@ import {Audit} from '../audit.js';
|
|
|
13
13
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
14
14
|
import {BaseNode} from '../../lib/dependency-graph/base-node.js';
|
|
15
15
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
16
|
-
import UnusedCSS from '../../computed/unused-css.js';
|
|
16
|
+
import {UnusedCSS} from '../../computed/unused-css.js';
|
|
17
17
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
18
|
-
import ProcessedTrace from '../../computed/processed-trace.js';
|
|
19
|
-
import ProcessedNavigation from '../../computed/processed-navigation.js';
|
|
20
|
-
import LoadSimulator from '../../computed/load-simulator.js';
|
|
21
|
-
import FirstContentfulPaint from '../../computed/metrics/first-contentful-paint.js';
|
|
18
|
+
import {ProcessedTrace} from '../../computed/processed-trace.js';
|
|
19
|
+
import {ProcessedNavigation} from '../../computed/processed-navigation.js';
|
|
20
|
+
import {LoadSimulator} from '../../computed/load-simulator.js';
|
|
21
|
+
import {FirstContentfulPaint} from '../../computed/metrics/first-contentful-paint.js';
|
|
22
22
|
|
|
23
23
|
/** @typedef {import('../../lib/dependency-graph/simulator/simulator').Simulator} Simulator */
|
|
24
24
|
/** @typedef {import('../../lib/dependency-graph/base-node.js').Node} Node */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {Audit} from '../audit.js';
|
|
8
8
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
9
9
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
10
|
-
import NetworkRecords from '../../computed/network-records.js';
|
|
10
|
+
import {NetworkRecords} from '../../computed/network-records.js';
|
|
11
11
|
|
|
12
12
|
const UIStrings = {
|
|
13
13
|
/** Title of a diagnostic audit that provides detail on large network resources required during page load. 'Payloads' is roughly equivalent to 'resources'. This descriptive title is shown to users when the amount is acceptable and no user action is required. */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
8
|
-
import UnusedCSS from '../../computed/unused-css.js';
|
|
8
|
+
import {UnusedCSS} from '../../computed/unused-css.js';
|
|
9
9
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
10
10
|
import {computeCSSTokenLength as computeTokenLength} from '../../lib/minification-estimator.js';
|
|
11
11
|
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
8
|
-
import
|
|
9
|
-
import
|
|
8
|
+
import {UnusedJavascriptSummary} from '../../computed/unused-javascript-summary.js';
|
|
9
|
+
import {JSBundles} from '../../computed/js-bundles.js';
|
|
10
10
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
11
|
import {getRequestForScript} from '../../lib/script-helpers.js';
|
|
12
12
|
|
|
@@ -79,7 +79,7 @@ class UnusedJavaScript extends ByteEfficiencyAudit {
|
|
|
79
79
|
* @return {Promise<import('./byte-efficiency-audit.js').ByteEfficiencyProduct>}
|
|
80
80
|
*/
|
|
81
81
|
static async audit_(artifacts, networkRecords, context) {
|
|
82
|
-
const bundles = await
|
|
82
|
+
const bundles = await JSBundles.request(artifacts, context);
|
|
83
83
|
const {
|
|
84
84
|
unusedThreshold = UNUSED_BYTES_IGNORE_THRESHOLD,
|
|
85
85
|
bundleSourceUnusedThreshold = UNUSED_BYTES_IGNORE_BUNDLE_SOURCE_THRESHOLD,
|
|
@@ -95,7 +95,7 @@ class UnusedJavaScript extends ByteEfficiencyAudit {
|
|
|
95
95
|
|
|
96
96
|
const bundle = bundles.find(b => b.script.scriptId === scriptId);
|
|
97
97
|
const unusedJsSummary =
|
|
98
|
-
await
|
|
98
|
+
await UnusedJavascriptSummary.request({scriptId, scriptCoverage, bundle}, context);
|
|
99
99
|
if (unusedJsSummary.wastedBytes === 0 || unusedJsSummary.totalBytes === 0) continue;
|
|
100
100
|
|
|
101
101
|
const transfer = ByteEfficiencyAudit
|
|
@@ -8,10 +8,10 @@ import parseCacheControl from 'parse-cache-control';
|
|
|
8
8
|
|
|
9
9
|
import {Audit} from '../audit.js';
|
|
10
10
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
11
|
-
import
|
|
11
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
12
12
|
import {linearInterpolation} from '../../lib/statistics.js';
|
|
13
13
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
14
|
-
import NetworkRecords from '../../computed/network-records.js';
|
|
14
|
+
import {NetworkRecords} from '../../computed/network-records.js';
|
|
15
15
|
|
|
16
16
|
const UIStrings = {
|
|
17
17
|
/** Title of a diagnostic audit that provides detail on the cache policy applies to the page's static assets. Cache refers to browser disk cache, which keeps old versions of network resources around for future use. This is displayed in a list of audit titles that Lighthouse generates. */
|
|
@@ -233,7 +233,7 @@ class CacheHeaders extends Audit {
|
|
|
233
233
|
const cacheHitProbability = CacheHeaders.getCacheHitProbability(cacheLifetimeInSeconds);
|
|
234
234
|
if (cacheHitProbability > IGNORE_THRESHOLD_IN_PERCENT) continue;
|
|
235
235
|
|
|
236
|
-
const url =
|
|
236
|
+
const url = UrlUtils.elideDataURI(record.url);
|
|
237
237
|
const totalBytes = record.transferSize || 0;
|
|
238
238
|
const wastedBytes = (1 - cacheHitProbability) * totalBytes;
|
|
239
239
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
13
|
-
import
|
|
13
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
14
14
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
15
15
|
|
|
16
16
|
const UIStrings = {
|
|
@@ -83,7 +83,7 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
83
83
|
const imageElement = imageElementsByURL.get(image.url);
|
|
84
84
|
|
|
85
85
|
if (image.failed) {
|
|
86
|
-
warnings.push(`Unable to decode ${
|
|
86
|
+
warnings.push(`Unable to decode ${UrlUtils.getURLDisplayName(image.url)}`);
|
|
87
87
|
continue;
|
|
88
88
|
} else if (/(jpeg|bmp)/.test(image.mimeType) === false) {
|
|
89
89
|
continue;
|
|
@@ -94,7 +94,7 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
94
94
|
|
|
95
95
|
if (typeof jpegSize === 'undefined') {
|
|
96
96
|
if (!imageElement) {
|
|
97
|
-
warnings.push(`Unable to locate resource ${
|
|
97
|
+
warnings.push(`Unable to locate resource ${UrlUtils.getURLDisplayName(image.url)}`);
|
|
98
98
|
continue;
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -111,8 +111,8 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
111
111
|
|
|
112
112
|
if (image.originalSize < jpegSize + IGNORE_THRESHOLD_IN_BYTES) continue;
|
|
113
113
|
|
|
114
|
-
const url =
|
|
115
|
-
const isCrossOrigin = !
|
|
114
|
+
const url = UrlUtils.elideDataURI(image.url);
|
|
115
|
+
const isCrossOrigin = !UrlUtils.originsMatch(pageURL, image.url);
|
|
116
116
|
const jpegSavings = UsesOptimizedImages.computeSavings({...image, jpegSize});
|
|
117
117
|
|
|
118
118
|
items.push({
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import {Audit} from '../audit.js';
|
|
15
15
|
import * as UsesResponsiveImages from './uses-responsive-images.js';
|
|
16
|
-
import
|
|
16
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
17
17
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
18
18
|
|
|
19
19
|
const UIStrings = {
|
|
@@ -71,7 +71,7 @@ class UsesResponsiveImagesSnapshot extends Audit {
|
|
|
71
71
|
|
|
72
72
|
items.push({
|
|
73
73
|
node: Audit.makeNodeItem(image.node),
|
|
74
|
-
url:
|
|
74
|
+
url: UrlUtils.elideDataURI(image.src),
|
|
75
75
|
displayedDimensions: `${displayed.width}x${displayed.height}`,
|
|
76
76
|
actualDimensions: `${actual.width}x${actual.height}`,
|
|
77
77
|
});
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
17
17
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
18
|
-
import ImageRecords from '../../computed/image-records.js';
|
|
19
|
-
import
|
|
18
|
+
import {ImageRecords} from '../../computed/image-records.js';
|
|
19
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
20
20
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
21
21
|
|
|
22
22
|
const UIStrings = {
|
|
@@ -100,7 +100,7 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
100
100
|
const displayed = this.getDisplayedDimensions(image, ViewportDimensions);
|
|
101
101
|
const usedPixels = displayed.width * displayed.height;
|
|
102
102
|
|
|
103
|
-
const url =
|
|
103
|
+
const url = UrlUtils.elideDataURI(image.src);
|
|
104
104
|
const actualPixels = image.naturalWidth * image.naturalHeight;
|
|
105
105
|
const wastedRatio = 1 - (usedPixels / actualPixels);
|
|
106
106
|
const totalBytes = NetworkRequest.getResourceSizeOnNetwork(networkRecord);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
13
|
-
import
|
|
13
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
14
14
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
15
15
|
|
|
16
16
|
const UIStrings = {
|
|
@@ -68,7 +68,7 @@ class ResponsesAreCompressed extends ByteEfficiencyAudit {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// remove duplicates
|
|
71
|
-
const url =
|
|
71
|
+
const url = UrlUtils.elideDataURI(record.url);
|
|
72
72
|
const isDuplicate = items.find(item => item.url === url &&
|
|
73
73
|
item.totalBytes === record.resourceSize);
|
|
74
74
|
if (isDuplicate) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {Audit} from './audit.js';
|
|
8
8
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
9
|
-
import ComputedChains from '../computed/critical-request-chains.js';
|
|
9
|
+
import {CriticalRequestChains as ComputedChains} from '../computed/critical-request-chains.js';
|
|
10
10
|
|
|
11
11
|
const UIStrings = {
|
|
12
12
|
/** Imperative title of a Lighthouse audit that tells the user to reduce the depth of critical network requests to enhance initial load of a page. Critical request chains are series of dependent network requests that are important for page rendering. For example, here's a 4-request-deep chain: The biglogo.jpg image is required, but is requested via the styles.css style code, which is requested by the initialize.js javascript, which is requested by the page's HTML. This is displayed in a list of audit titles that Lighthouse generates. */
|
package/core/audits/csp-xss.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {Audit} from './audit.js';
|
|
8
|
-
import MainResource from '../computed/main-resource.js';
|
|
8
|
+
import {MainResource} from '../computed/main-resource.js';
|
|
9
9
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
10
10
|
import {evaluateRawCspsForXss, getTranslatedDescription} from '../lib/csp-evaluator.js';
|
|
11
11
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import {Audit} from './audit.js';
|
|
12
|
-
import
|
|
12
|
+
import {JSBundles} from '../computed/js-bundles.js';
|
|
13
13
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
14
14
|
import {getIssueDetailDescription} from '../lib/deprecations-strings.js';
|
|
15
15
|
|
|
@@ -56,7 +56,7 @@ class Deprecations extends Audit {
|
|
|
56
56
|
* @return {Promise<LH.Audit.Product>}
|
|
57
57
|
*/
|
|
58
58
|
static async audit(artifacts, context) {
|
|
59
|
-
const bundles = await
|
|
59
|
+
const bundles = await JSBundles.request(artifacts, context);
|
|
60
60
|
|
|
61
61
|
const deprecations = artifacts.InspectorIssues.deprecationIssue
|
|
62
62
|
.map(deprecation => {
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {Audit} from './audit.js';
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import MainResource from '../computed/main-resource.js';
|
|
8
|
+
import {MainThreadTasks} from '../computed/main-thread-tasks.js';
|
|
9
|
+
import {NetworkRecords} from '../computed/network-records.js';
|
|
10
|
+
import {NetworkAnalysis} from '../computed/network-analysis.js';
|
|
11
|
+
import {MainResource} from '../computed/main-resource.js';
|
|
12
12
|
|
|
13
13
|
class Diagnostics extends Audit {
|
|
14
14
|
/**
|
|
@@ -33,9 +33,9 @@ class Diagnostics extends Audit {
|
|
|
33
33
|
static async audit(artifacts, context) {
|
|
34
34
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
35
35
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
36
|
-
const tasks = await
|
|
37
|
-
const records = await
|
|
38
|
-
const analysis = await
|
|
36
|
+
const tasks = await MainThreadTasks.request(trace, context);
|
|
37
|
+
const records = await NetworkRecords.request(devtoolsLog, context);
|
|
38
|
+
const analysis = await NetworkAnalysis.request(devtoolsLog, context);
|
|
39
39
|
const mainResource = await MainResource.request({devtoolsLog, URL: artifacts.URL}, context);
|
|
40
40
|
|
|
41
41
|
const toplevelTasks = tasks.filter(t => !t.parent);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import {Audit} from '../audit.js';
|
|
16
16
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
17
|
-
import MainResource from '../../computed/main-resource.js';
|
|
17
|
+
import {MainResource} from '../../computed/main-resource.js';
|
|
18
18
|
|
|
19
19
|
const UIStrings = {
|
|
20
20
|
/** Title of a Lighthouse audit that provides detail on if the charset is set properly for a page. This title is shown when the charset is defined correctly. Charset defines the character encoding (eg UTF-8) of the page content. */
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
|
|
15
15
|
import {Audit} from '../audit.js';
|
|
16
16
|
import ThirdParty from '../../lib/third-party-web.js';
|
|
17
|
-
import
|
|
17
|
+
import UrlUtils from '../../lib/url-utils.js';
|
|
18
18
|
import {ByteEfficiencyAudit} from '../byte-efficiency/byte-efficiency-audit.js';
|
|
19
|
-
import
|
|
19
|
+
import {LanternInteractive} from '../../computed/metrics/lantern-interactive.js';
|
|
20
20
|
import {NetworkRequest} from '../../lib/network-request.js';
|
|
21
|
-
import NetworkRecords from '../../computed/network-records.js';
|
|
22
|
-
import LoadSimulator from '../../computed/load-simulator.js';
|
|
23
|
-
import PageDependencyGraph from '../../computed/page-dependency-graph.js';
|
|
21
|
+
import {NetworkRecords} from '../../computed/network-records.js';
|
|
22
|
+
import {LoadSimulator} from '../../computed/load-simulator.js';
|
|
23
|
+
import {PageDependencyGraph} from '../../computed/page-dependency-graph.js';
|
|
24
24
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
25
25
|
|
|
26
26
|
const UIStrings = {
|
|
@@ -106,8 +106,8 @@ class UsesHTTP2Audit extends Audit {
|
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
const savingsOnOverallLoad = simulationBefore.timeInMs - simulationAfter.timeInMs;
|
|
109
|
-
const savingsOnTTI =
|
|
110
|
-
|
|
109
|
+
const savingsOnTTI = LanternInteractive.getLastLongTaskEndTime(simulationBefore.nodeTimings) -
|
|
110
|
+
LanternInteractive.getLastLongTaskEndTime(simulationAfter.nodeTimings);
|
|
111
111
|
const savings = Math.max(savingsOnTTI, savingsOnOverallLoad);
|
|
112
112
|
|
|
113
113
|
// Round waste to nearest 10ms
|
|
@@ -167,7 +167,7 @@ class UsesHTTP2Audit extends Audit {
|
|
|
167
167
|
const groupedByOrigin = new Map();
|
|
168
168
|
for (const record of networkRecords) {
|
|
169
169
|
if (!UsesHTTP2Audit.isStaticAsset(record)) continue;
|
|
170
|
-
if (
|
|
170
|
+
if (UrlUtils.isLikeLocalhost(record.parsedURL.host)) continue;
|
|
171
171
|
const existing = groupedByOrigin.get(record.parsedURL.securityOrigin) || [];
|
|
172
172
|
existing.push(record);
|
|
173
173
|
groupedByOrigin.set(record.parsedURL.securityOrigin, existing);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import log from 'lighthouse-logger';
|
|
13
13
|
|
|
14
14
|
import {Audit} from './audit.js';
|
|
15
|
-
import
|
|
15
|
+
import {JSBundles} from '../computed/js-bundles.js';
|
|
16
16
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
17
17
|
|
|
18
18
|
const UIStrings = {
|
|
@@ -81,7 +81,7 @@ class ErrorLogs extends Audit {
|
|
|
81
81
|
static async audit(artifacts, context) {
|
|
82
82
|
/** @type {AuditOptions} */
|
|
83
83
|
const auditOptions = context.options;
|
|
84
|
-
const bundles = await
|
|
84
|
+
const bundles = await JSBundles.request(artifacts, context);
|
|
85
85
|
|
|
86
86
|
/** @type {Array<{source: string, description: string|undefined, sourceLocation: LH.Audit.Details.SourceLocationValue|undefined}>} */
|
|
87
87
|
const consoleRows = artifacts.ConsoleMessages
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import {Audit} from './audit.js';
|
|
8
8
|
import {LighthouseError} from '../lib/lh-error.js';
|
|
9
|
-
import ProcessedTrace from '../computed/processed-trace.js';
|
|
10
|
-
import Screenshots from '../computed/screenshots.js';
|
|
9
|
+
import {ProcessedTrace} from '../computed/processed-trace.js';
|
|
10
|
+
import {Screenshots} from '../computed/screenshots.js';
|
|
11
11
|
|
|
12
12
|
class FinalScreenshot extends Audit {
|
|
13
13
|
/**
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {Audit} from './audit.js';
|
|
8
|
-
import
|
|
8
|
+
import UrlUtils from '../lib/url-utils.js';
|
|
9
|
+
import * as i18n from '../lib/i18n/i18n.js';
|
|
10
|
+
import {Sentry} from '../lib/sentry.js';
|
|
11
|
+
import {NetworkRecords} from '../computed/network-records.js';
|
|
12
|
+
|
|
9
13
|
const PASSING_FONT_DISPLAY_REGEX = /^(block|fallback|optional|swap)$/;
|
|
10
14
|
const CSS_URL_REGEX = /url\((.*?)\)/;
|
|
11
15
|
const CSS_URL_GLOBAL_REGEX = new RegExp(CSS_URL_REGEX, 'g');
|
|
12
|
-
import * as i18n from '../lib/i18n/i18n.js';
|
|
13
|
-
import {Sentry} from '../lib/sentry.js';
|
|
14
|
-
import NetworkRecords from '../computed/network-records.js';
|
|
15
16
|
|
|
16
17
|
const UIStrings = {
|
|
17
18
|
/** Title of a diagnostic audit that provides detail on if all the text on a webpage was visible while the page was loading its webfonts. This descriptive title is shown to users when the amount is acceptable and no user action is required. */
|
|
@@ -98,7 +99,7 @@ class FontDisplay extends Audit {
|
|
|
98
99
|
// Convert the relative CSS URL to an absolute URL and add it to the target set.
|
|
99
100
|
for (const relativeURL of relativeURLs) {
|
|
100
101
|
try {
|
|
101
|
-
const relativeRoot =
|
|
102
|
+
const relativeRoot = UrlUtils.isValid(stylesheet.header.sourceURL) ?
|
|
102
103
|
stylesheet.header.sourceURL : artifacts.URL.finalUrl;
|
|
103
104
|
const absoluteURL = new URL(relativeURL, relativeRoot);
|
|
104
105
|
targetURLSet.add(absoluteURL.href);
|
|
@@ -121,7 +122,7 @@ class FontDisplay extends Audit {
|
|
|
121
122
|
/** @type {Map<string, number>} */
|
|
122
123
|
const warningCountByOrigin = new Map();
|
|
123
124
|
for (const warningUrl of warningUrls) {
|
|
124
|
-
const origin =
|
|
125
|
+
const origin = UrlUtils.getOrigin(warningUrl);
|
|
125
126
|
if (!origin) continue;
|
|
126
127
|
|
|
127
128
|
const count = warningCountByOrigin.get(origin) || 0;
|