lighthouse 8.0.0-dev.20210709 → 8.0.0
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/docs/architecture.md +101 -0
- package/docs/authenticated-pages.md +44 -0
- package/docs/bug-labels.md +35 -0
- package/docs/configuration.md +213 -0
- package/docs/emulation.md +32 -0
- package/docs/error-reporting.md +42 -0
- package/docs/hacking-tips.md +55 -0
- package/docs/headless-chrome.md +119 -0
- package/docs/lantern.md +55 -0
- package/docs/new-audits.md +99 -0
- package/docs/performance-budgets.md +187 -0
- package/docs/plugins.md +374 -0
- package/docs/puppeteer.md +95 -0
- package/docs/readme.md +164 -0
- package/docs/recipes/auth/README.md +129 -0
- package/docs/recipes/auth/example-lh-auth.js +81 -0
- package/docs/recipes/auth/package.json +11 -0
- package/docs/recipes/auth/server/public/dashboard-unauthenticated.html +21 -0
- package/docs/recipes/auth/server/public/dashboard.html +25 -0
- package/docs/recipes/auth/server/public/home-unauthenticated.html +27 -0
- package/docs/recipes/auth/server/public/home.html +17 -0
- package/docs/recipes/auth/server/public/unauthenticated.html +22 -0
- package/docs/recipes/auth/server/server.js +85 -0
- package/docs/recipes/custom-audit/custom-config.js +36 -0
- package/docs/recipes/custom-audit/package.json +8 -0
- package/docs/recipes/custom-audit/readme.md +32 -0
- package/docs/recipes/custom-audit/searchable-audit.js +46 -0
- package/docs/recipes/custom-audit/searchable-gatherer.js +32 -0
- package/docs/recipes/custom-gatherer-puppeteer/custom-audit.js +34 -0
- package/{root.js → docs/recipes/custom-gatherer-puppeteer/custom-config.js} +23 -2
- package/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js +51 -0
- package/docs/recipes/custom-gatherer-puppeteer/package.json +13 -0
- package/docs/recipes/custom-gatherer-puppeteer/readme.md +7 -0
- package/docs/recipes/custom-gatherer-puppeteer/test.sh +9 -0
- package/docs/recipes/gulp/gulpfile.js +79 -0
- package/docs/recipes/gulp/package.json +12 -0
- package/docs/recipes/gulp/public/index.html +22 -0
- package/docs/recipes/gulp/readme.md +6 -0
- package/docs/recipes/integration-test/README.md +14 -0
- package/docs/recipes/integration-test/example-lh-auth.test.js +160 -0
- package/docs/recipes/integration-test/package.json +9 -0
- package/docs/recipes/lighthouse-plugin-example/audits/preload-as.js +46 -0
- package/docs/recipes/lighthouse-plugin-example/package.json +11 -0
- package/docs/recipes/lighthouse-plugin-example/plugin-recipe-screenshot.png +0 -0
- package/docs/recipes/lighthouse-plugin-example/plugin.js +24 -0
- package/docs/recipes/lighthouse-plugin-example/readme.md +53 -0
- package/docs/releasing.md +164 -0
- package/docs/scoring.md +79 -0
- package/docs/throttling.md +150 -0
- package/docs/understanding-results.md +209 -0
- package/docs/v8-perf-faq.md +244 -0
- package/docs/variability.md +150 -0
- package/jest.config.js +0 -3
- package/lighthouse-cli/bin.js +8 -6
- package/lighthouse-core/audits/accessibility/aria-command-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-tooltip-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/lighthouse-core/audits/apple-touch-icon.js +0 -1
- package/lighthouse-core/audits/audit.js +3 -3
- package/lighthouse-core/audits/autocomplete.js +2 -2
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +14 -29
- package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/modern-image-formats.js +15 -55
- package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +4 -8
- package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +8 -15
- package/lighthouse-core/audits/byte-efficiency/total-byte-weight.js +9 -10
- package/lighthouse-core/audits/byte-efficiency/unminified-css.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js +2 -2
- package/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +24 -46
- package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
- package/lighthouse-core/audits/critical-request-chains.js +0 -1
- package/lighthouse-core/audits/csp-xss.js +1 -1
- package/lighthouse-core/audits/diagnostics.js +0 -1
- package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +0 -1
- package/lighthouse-core/audits/dobetterweb/inspector-issues.js +1 -1
- package/lighthouse-core/audits/dobetterweb/notification-on-start.js +0 -1
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +0 -1
- package/lighthouse-core/audits/final-screenshot.js +4 -8
- package/lighthouse-core/audits/font-display.js +0 -1
- package/lighthouse-core/audits/installable-manifest.js +3 -4
- package/lighthouse-core/audits/largest-contentful-paint-element.js +0 -1
- package/lighthouse-core/audits/long-tasks.js +1 -1
- package/lighthouse-core/audits/maskable-icon.js +0 -1
- package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -4
- package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -4
- package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -4
- package/lighthouse-core/audits/metrics/interactive.js +2 -4
- package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -4
- package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -4
- package/lighthouse-core/audits/metrics/speed-index.js +2 -4
- package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -10
- package/lighthouse-core/audits/metrics.js +2 -4
- package/lighthouse-core/audits/performance-budget.js +0 -1
- package/lighthouse-core/audits/predictive-perf.js +6 -9
- package/lighthouse-core/audits/preload-fonts.js +1 -11
- package/lighthouse-core/audits/preload-lcp-image.js +5 -18
- package/lighthouse-core/audits/redirects.js +8 -10
- package/lighthouse-core/audits/screenshot-thumbnails.js +13 -28
- package/lighthouse-core/audits/seo/canonical.js +1 -2
- package/lighthouse-core/audits/seo/font-size.js +4 -4
- package/lighthouse-core/audits/seo/hreflang.js +2 -3
- package/lighthouse-core/audits/seo/http-status-code.js +16 -21
- package/lighthouse-core/audits/seo/is-crawlable.js +3 -4
- package/lighthouse-core/audits/seo/robots-txt.js +2 -2
- package/lighthouse-core/audits/seo/tap-targets.js +5 -5
- package/lighthouse-core/audits/server-response-time.js +2 -20
- package/lighthouse-core/audits/splash-screen.js +0 -1
- package/lighthouse-core/audits/themed-omnibox.js +0 -1
- package/lighthouse-core/audits/third-party-facades.js +0 -1
- package/lighthouse-core/audits/third-party-summary.js +3 -1
- package/lighthouse-core/audits/timing-budget.js +2 -4
- package/lighthouse-core/audits/uses-rel-preconnect.js +9 -14
- package/lighthouse-core/audits/uses-rel-preload.js +2 -13
- package/lighthouse-core/computed/main-thread-tasks.js +2 -2
- package/lighthouse-core/computed/metrics/cumulative-layout-shift.js +3 -3
- package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +6 -6
- package/lighthouse-core/computed/metrics/first-contentful-paint.js +8 -9
- package/lighthouse-core/computed/metrics/first-meaningful-paint.js +9 -10
- package/lighthouse-core/computed/metrics/interactive.js +24 -25
- package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +6 -6
- package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +6 -6
- package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +6 -6
- package/lighthouse-core/computed/metrics/lantern-metric.js +8 -16
- package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +7 -7
- package/lighthouse-core/computed/metrics/largest-contentful-paint.js +9 -10
- package/lighthouse-core/computed/metrics/max-potential-fid.js +11 -8
- package/lighthouse-core/computed/metrics/metric.js +5 -32
- package/lighthouse-core/computed/metrics/speed-index.js +5 -6
- package/lighthouse-core/computed/metrics/timing-summary.js +45 -55
- package/lighthouse-core/computed/metrics/total-blocking-time.js +29 -36
- package/lighthouse-core/computed/page-dependency-graph.js +14 -14
- package/lighthouse-core/computed/resource-summary.js +7 -3
- package/lighthouse-core/computed/speedline.js +3 -3
- package/lighthouse-core/computed/trace-of-tab.js +86 -15
- package/lighthouse-core/computed/user-timings.js +5 -5
- package/lighthouse-core/config/default-config.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +7 -9
- package/lighthouse-core/fraggle-rock/config/default-config.js +2 -40
- package/lighthouse-core/fraggle-rock/config/filters.js +6 -39
- package/lighthouse-core/fraggle-rock/config/validation.js +4 -4
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +19 -54
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +10 -21
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +2 -2
- package/lighthouse-core/gather/driver/prepare.js +0 -3
- package/lighthouse-core/gather/fetcher.js +2 -0
- package/lighthouse-core/gather/gather-runner.js +14 -2
- package/lighthouse-core/gather/gatherers/image-elements.js +61 -24
- package/lighthouse-core/gather/gatherers/inspector-issues.js +2 -2
- package/lighthouse-core/gather/gatherers/script-elements.js +12 -45
- package/lighthouse-core/gather/gatherers/seo/font-size.js +5 -5
- package/lighthouse-core/gather/gatherers/seo/tap-targets.js +12 -64
- package/lighthouse-core/gather/gatherers/service-worker.js +3 -20
- package/lighthouse-core/gather/gatherers/trace-compat.js +1 -1
- package/lighthouse-core/gather/gatherers/trace-elements.js +3 -15
- package/lighthouse-core/gather/gatherers/trace.js +4 -13
- package/lighthouse-core/gather/gatherers/viewport-dimensions.js +1 -1
- package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +2 -13
- package/lighthouse-core/lib/emulation.js +2 -0
- package/lighthouse-core/lib/i18n/i18n.js +2 -2
- package/lighthouse-core/lib/i18n/locales/ar-XB.json +141 -141
- package/lighthouse-core/lib/i18n/locales/ar.json +143 -143
- package/lighthouse-core/lib/i18n/locales/bg.json +143 -143
- package/lighthouse-core/lib/i18n/locales/ca.json +141 -141
- package/lighthouse-core/lib/i18n/locales/cs.json +141 -141
- package/lighthouse-core/lib/i18n/locales/da.json +141 -141
- package/lighthouse-core/lib/i18n/locales/de.json +142 -142
- package/lighthouse-core/lib/i18n/locales/el.json +141 -141
- package/lighthouse-core/lib/i18n/locales/en-GB.json +141 -141
- package/lighthouse-core/lib/i18n/locales/en-US.ctc.json +6659 -0
- package/lighthouse-core/lib/i18n/locales/en-US.json +144 -150
- package/lighthouse-core/lib/i18n/locales/en-XA.json +141 -141
- package/lighthouse-core/lib/i18n/locales/en-XL.ctc.json +6628 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +144 -150
- package/lighthouse-core/lib/i18n/locales/es-419.json +141 -141
- package/lighthouse-core/lib/i18n/locales/es.json +141 -141
- package/lighthouse-core/lib/i18n/locales/fi.json +143 -143
- package/lighthouse-core/lib/i18n/locales/fil.json +142 -142
- package/lighthouse-core/lib/i18n/locales/fr.json +141 -141
- package/lighthouse-core/lib/i18n/locales/he.json +142 -142
- package/lighthouse-core/lib/i18n/locales/hi.json +143 -143
- package/lighthouse-core/lib/i18n/locales/hr.json +141 -141
- package/lighthouse-core/lib/i18n/locales/hu.json +143 -143
- package/lighthouse-core/lib/i18n/locales/id.json +143 -143
- package/lighthouse-core/lib/i18n/locales/it.json +143 -143
- package/lighthouse-core/lib/i18n/locales/ja.json +143 -143
- package/lighthouse-core/lib/i18n/locales/ko.json +143 -143
- package/lighthouse-core/lib/i18n/locales/lt.json +143 -143
- package/lighthouse-core/lib/i18n/locales/lv.json +143 -143
- package/lighthouse-core/lib/i18n/locales/nl.json +141 -141
- package/lighthouse-core/lib/i18n/locales/no.json +141 -141
- package/lighthouse-core/lib/i18n/locales/pl.json +141 -141
- package/lighthouse-core/lib/i18n/locales/pt-PT.json +141 -141
- package/lighthouse-core/lib/i18n/locales/pt.json +141 -141
- package/lighthouse-core/lib/i18n/locales/ro.json +144 -144
- package/lighthouse-core/lib/i18n/locales/ru.json +143 -143
- package/lighthouse-core/lib/i18n/locales/sk.json +142 -142
- package/lighthouse-core/lib/i18n/locales/sl.json +141 -141
- package/lighthouse-core/lib/i18n/locales/sr-Latn.json +143 -143
- package/lighthouse-core/lib/i18n/locales/sr.json +143 -143
- package/lighthouse-core/lib/i18n/locales/sv.json +142 -142
- package/lighthouse-core/lib/i18n/locales/ta.json +141 -141
- package/lighthouse-core/lib/i18n/locales/te.json +143 -143
- package/lighthouse-core/lib/i18n/locales/th.json +143 -143
- package/lighthouse-core/lib/i18n/locales/tr.json +143 -143
- package/lighthouse-core/lib/i18n/locales/uk.json +141 -141
- package/lighthouse-core/lib/i18n/locales/vi.json +143 -143
- package/lighthouse-core/lib/i18n/locales/zh-HK.json +141 -141
- package/lighthouse-core/lib/i18n/locales/zh-TW.json +143 -143
- package/lighthouse-core/lib/i18n/locales/zh.json +143 -143
- package/lighthouse-core/lib/lh-error.js +2 -2
- package/lighthouse-core/lib/minify-trace.js +1 -1
- package/lighthouse-core/lib/network-request.js +1 -17
- package/lighthouse-core/lib/page-functions.js +5 -6
- package/lighthouse-core/lib/rect-helpers.js +3 -3
- package/lighthouse-core/lib/sd-validation/assets/jsonldcontext.json +7137 -0
- package/lighthouse-core/lib/sd-validation/assets/schema-tree.json +9900 -0
- package/{report/report-assets.js → lighthouse-core/lib/sd-validation/helpers/walk-object.js} +20 -12
- package/lighthouse-core/lib/sd-validation/json-expander.js +56 -0
- package/lighthouse-core/lib/sd-validation/json-linter.js +49 -0
- package/lighthouse-core/lib/sd-validation/jsonld-keyword-validator.js +50 -0
- package/lighthouse-core/lib/sd-validation/line-number-from-jsonld-path.js +60 -0
- package/lighthouse-core/lib/sd-validation/schema-validator.js +146 -0
- package/lighthouse-core/lib/sd-validation/scripts/download-jsonldcontext.js +30 -0
- package/lighthouse-core/lib/sd-validation/scripts/generate-schema-tree.js +97 -0
- package/lighthouse-core/lib/sd-validation/sd-validation.js +77 -0
- package/lighthouse-core/lib/tappable-rects.js +1 -1
- package/lighthouse-core/lib/tracehouse/trace-processor.js +42 -116
- package/lighthouse-core/lib/url-shim.js +2 -29
- package/lighthouse-core/report/html/html-report-assets.js +38 -0
- package/{report/README.md → lighthouse-core/report/html/readme.md} +11 -7
- package/{report → lighthouse-core/report/html}/renderer/category-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/crc-details-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/details-renderer.js +1 -1
- package/{report → lighthouse-core/report/html}/renderer/dom.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/element-screenshot-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/i18n.js +1 -1
- package/{report → lighthouse-core/report/html}/renderer/logger.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/performance-category-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/psi.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/pwa-category-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/report-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/report-ui-features.js +3 -3
- package/{report → lighthouse-core/report/html}/renderer/snippet-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/text-encoding.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/util.js +4 -7
- package/{report/assets/styles.css → lighthouse-core/report/html/report-styles.css} +0 -0
- package/{report/assets/standalone-template.html → lighthouse-core/report/html/report-template.html} +41 -1
- package/{report/assets → lighthouse-core/report/html}/templates.html +0 -0
- package/{report → lighthouse-core/report}/report-generator.js +1 -1
- package/lighthouse-core/runner.js +1 -1
- package/package.json +12 -13
- package/readme.md +2 -2
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -3
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -2
- package/third-party/download-content-shell/download-content-shell.js +1 -2
- package/third-party/snyk/snapshot.json +1 -1
- package/tsconfig.json +1 -0
- package/types/artifacts.d.ts +21 -41
- package/types/audit.d.ts +0 -2
- package/types/config.d.ts +2 -16
- package/types/externs.d.ts +0 -1
- package/types/gatherer.d.ts +13 -13
- package/types/html-renderer.d.ts +14 -14
- package/types/i18n.d.ts +1 -1
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +0 -94
- package/lighthouse-core/computed/image-records.js +0 -62
- package/lighthouse-core/computed/metrics/navigation-metric.js +0 -46
- package/lighthouse-core/computed/processed-navigation.js +0 -21
- package/lighthouse-core/computed/processed-trace.js +0 -21
- package/lighthouse-core/gather/gatherers/gather-context.js +0 -25
- package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
- package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
- package/lighthouse-core/lib/lh-trace-processor.js +0 -46
- package/report/clients/standalone.js +0 -52
- package/report/test/renderer/category-renderer-test.js +0 -488
- package/report/test/renderer/crc-details-renderer-test.js +0 -115
- package/report/test/renderer/details-renderer-test.js +0 -843
- package/report/test/renderer/dom-test.js +0 -157
- package/report/test/renderer/element-screenshot-renderer-test.js +0 -189
- package/report/test/renderer/i18n-test.js +0 -146
- package/report/test/renderer/performance-category-renderer-test.js +0 -332
- package/report/test/renderer/psi-test.js +0 -152
- package/report/test/renderer/pwa-category-renderer-test.js +0 -303
- package/report/test/renderer/report-renderer-test.js +0 -325
- package/report/test/renderer/report-ui-features-test.js +0 -572
- package/report/test/renderer/snippet-renderer-test.js +0 -291
- package/report/test/renderer/text-encoding-test.js +0 -41
- package/report/test/renderer/util-test.js +0 -388
- package/report/test/report-generator-test.js +0 -145
|
@@ -48,8 +48,7 @@ class DuplicatedJavascript extends ByteEfficiencyAudit {
|
|
|
48
48
|
title: str_(UIStrings.title),
|
|
49
49
|
description: str_(UIStrings.description),
|
|
50
50
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
51
|
-
requiredArtifacts: ['devtoolsLogs', 'traces', 'SourceMaps', 'ScriptElements',
|
|
52
|
-
'GatherContext', 'URL'],
|
|
51
|
+
requiredArtifacts: ['devtoolsLogs', 'traces', 'SourceMaps', 'ScriptElements', 'URL'],
|
|
53
52
|
};
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -130,7 +129,7 @@ class DuplicatedJavascript extends ByteEfficiencyAudit {
|
|
|
130
129
|
context.options && context.options.ignoreThresholdInBytes || IGNORE_THRESHOLD_IN_BYTES;
|
|
131
130
|
const duplication =
|
|
132
131
|
await DuplicatedJavascript._getDuplicationGroupedByNodeModules(artifacts, context);
|
|
133
|
-
const mainDocumentRecord = NetworkAnalyzer.
|
|
132
|
+
const mainDocumentRecord = await NetworkAnalyzer.findMainDocument(networkRecords);
|
|
134
133
|
|
|
135
134
|
/** @type {Map<string, number>} */
|
|
136
135
|
const transferRatioByUrl = new Map();
|
|
@@ -37,7 +37,7 @@ class EfficientAnimatedContent extends ByteEfficiencyAudit {
|
|
|
37
37
|
title: str_(UIStrings.title),
|
|
38
38
|
description: str_(UIStrings.description),
|
|
39
39
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
40
|
-
requiredArtifacts: ['devtoolsLogs', 'traces'
|
|
40
|
+
requiredArtifacts: ['devtoolsLogs', 'traces'],
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -109,8 +109,7 @@ class LegacyJavascript extends ByteEfficiencyAudit {
|
|
|
109
109
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
110
110
|
description: str_(UIStrings.description),
|
|
111
111
|
title: str_(UIStrings.title),
|
|
112
|
-
requiredArtifacts: ['devtoolsLogs', 'traces', 'ScriptElements', 'SourceMaps',
|
|
113
|
-
'GatherContext', 'URL'],
|
|
112
|
+
requiredArtifacts: ['devtoolsLogs', 'traces', 'ScriptElements', 'SourceMaps', 'URL'],
|
|
114
113
|
};
|
|
115
114
|
}
|
|
116
115
|
|
|
@@ -377,7 +376,7 @@ class LegacyJavascript extends ByteEfficiencyAudit {
|
|
|
377
376
|
let transferRatio = transferRatioByUrl.get(url);
|
|
378
377
|
if (transferRatio !== undefined) return transferRatio;
|
|
379
378
|
|
|
380
|
-
const mainDocumentRecord = NetworkAnalyzer.
|
|
379
|
+
const mainDocumentRecord = await NetworkAnalyzer.findMainDocument(networkRecords);
|
|
381
380
|
const networkRecord = url === artifacts.URL.finalUrl ?
|
|
382
381
|
mainDocumentRecord :
|
|
383
382
|
networkRecords.find(n => n.url === url);
|
|
@@ -16,7 +16,7 @@ const UIStrings = {
|
|
|
16
16
|
/** Imperative title of a Lighthouse audit that tells the user to serve images in newer and more efficient image formats in order to enhance the performance of a page. A non-modern image format was designed 20+ years ago. This is displayed in a list of audit titles that Lighthouse generates. */
|
|
17
17
|
title: 'Serve images in next-gen formats',
|
|
18
18
|
/** Description of a Lighthouse audit that tells the user *why* they should use newer and more efficient image formats. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
|
|
19
|
-
description: 'Image formats like
|
|
19
|
+
description: 'Image formats like JPEG 2000, JPEG XR, and WebP often provide better ' +
|
|
20
20
|
'compression than PNG or JPEG, which means faster downloads and less data consumption. ' +
|
|
21
21
|
'[Learn more](https://web.dev/uses-webp-images/).',
|
|
22
22
|
};
|
|
@@ -35,11 +35,20 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
35
35
|
title: str_(UIStrings.title),
|
|
36
36
|
description: str_(UIStrings.description),
|
|
37
37
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
38
|
-
requiredArtifacts: ['OptimizedImages', 'devtoolsLogs', 'traces', 'URL', '
|
|
39
|
-
'ImageElements'],
|
|
38
|
+
requiredArtifacts: ['OptimizedImages', 'devtoolsLogs', 'traces', 'URL', 'ImageElements'],
|
|
40
39
|
};
|
|
41
40
|
}
|
|
42
41
|
|
|
42
|
+
/**
|
|
43
|
+
* @param {{originalSize: number, webpSize: number}} image
|
|
44
|
+
* @return {{bytes: number, percent: number}}
|
|
45
|
+
*/
|
|
46
|
+
static computeSavings(image) {
|
|
47
|
+
const bytes = image.originalSize - image.webpSize;
|
|
48
|
+
const percent = 100 * bytes / image.originalSize;
|
|
49
|
+
return {bytes, percent};
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
/**
|
|
44
53
|
* @param {{naturalWidth: number, naturalHeight: number}} imageElement
|
|
45
54
|
* @return {number}
|
|
@@ -55,38 +64,6 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
55
64
|
return Math.round(totalPixels * expectedBytesPerPixel);
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
/**
|
|
59
|
-
* @param {{naturalWidth: number, naturalHeight: number}} imageElement
|
|
60
|
-
* @return {number}
|
|
61
|
-
*/
|
|
62
|
-
static estimateAvifSizeFromDimensions(imageElement) {
|
|
63
|
-
const totalPixels = imageElement.naturalWidth * imageElement.naturalHeight;
|
|
64
|
-
// See above for the rationale behind our 2 byte-per-pixel baseline and WebP ratio of 10:1.
|
|
65
|
-
// AVIF usually gives ~20% additional savings on top of that, so we will use 12:1.
|
|
66
|
-
// This is quite pessimistic as Netflix study shows a photographic compression ratio of ~40:1
|
|
67
|
-
// (0.4 *bits* per pixel at SSIM 0.97).
|
|
68
|
-
// https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4
|
|
69
|
-
const expectedBytesPerPixel = 2 * 1 / 12;
|
|
70
|
-
return Math.round(totalPixels * expectedBytesPerPixel);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @param {{jpegSize: number | undefined, webpSize: number | undefined}} otherFormatSizes
|
|
75
|
-
* @return {number|undefined}
|
|
76
|
-
*/
|
|
77
|
-
static estimateAvifSizeFromWebPAndJpegEstimates(otherFormatSizes) {
|
|
78
|
-
if (!otherFormatSizes.jpegSize || !otherFormatSizes.webpSize) return undefined;
|
|
79
|
-
|
|
80
|
-
// AVIF saves at least ~50% on JPEG, ~20% on WebP at low quality.
|
|
81
|
-
// http://downloads.aomedia.org/assets/pdf/symposium-2019/slides/CyrilConcolato_Netflix-AVIF-AOM-Research-Symposium-2019.pdf
|
|
82
|
-
// https://jakearchibald.com/2020/avif-has-landed/
|
|
83
|
-
// https://www.finally.agency/blog/what-is-avif-image-format
|
|
84
|
-
// See https://github.com/GoogleChrome/lighthouse/issues/12295#issue-840261460 for more.
|
|
85
|
-
const estimateFromJpeg = otherFormatSizes.jpegSize * 5 / 10;
|
|
86
|
-
const estimateFromWebp = otherFormatSizes.webpSize * 8 / 10;
|
|
87
|
-
return estimateFromJpeg / 2 + estimateFromWebp / 2;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
67
|
/**
|
|
91
68
|
* @param {LH.Artifacts} artifacts
|
|
92
69
|
* @return {ByteEfficiencyAudit.ByteEfficiencyProduct}
|
|
@@ -108,15 +85,7 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
108
85
|
continue;
|
|
109
86
|
}
|
|
110
87
|
|
|
111
|
-
// Skip if the image was already using a modern format.
|
|
112
|
-
if (image.mimeType === 'image/webp' || image.mimeType === 'image/avif') continue;
|
|
113
|
-
|
|
114
|
-
const jpegSize = image.jpegSize;
|
|
115
88
|
let webpSize = image.webpSize;
|
|
116
|
-
let avifSize = ModernImageFormats.estimateAvifSizeFromWebPAndJpegEstimates({
|
|
117
|
-
jpegSize,
|
|
118
|
-
webpSize,
|
|
119
|
-
});
|
|
120
89
|
let fromProtocol = true;
|
|
121
90
|
|
|
122
91
|
if (typeof webpSize === 'undefined') {
|
|
@@ -137,30 +106,21 @@ class ModernImageFormats extends ByteEfficiencyAudit {
|
|
|
137
106
|
naturalHeight,
|
|
138
107
|
naturalWidth,
|
|
139
108
|
});
|
|
140
|
-
avifSize = ModernImageFormats.estimateAvifSizeFromDimensions({
|
|
141
|
-
naturalHeight,
|
|
142
|
-
naturalWidth,
|
|
143
|
-
});
|
|
144
109
|
fromProtocol = false;
|
|
145
110
|
}
|
|
146
111
|
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
// Visible wasted bytes uses AVIF, but we still include the WebP savings in the LHR.
|
|
150
|
-
const wastedWebpBytes = image.originalSize - webpSize;
|
|
151
|
-
const wastedBytes = image.originalSize - avifSize;
|
|
152
|
-
if (wastedBytes < IGNORE_THRESHOLD_IN_BYTES) continue;
|
|
112
|
+
if (image.originalSize < webpSize + IGNORE_THRESHOLD_IN_BYTES) continue;
|
|
153
113
|
|
|
154
114
|
const url = URL.elideDataURI(image.url);
|
|
155
115
|
const isCrossOrigin = !URL.originsMatch(pageURL, image.url);
|
|
116
|
+
const webpSavings = ModernImageFormats.computeSavings({...image, webpSize: webpSize});
|
|
156
117
|
|
|
157
118
|
items.push({
|
|
158
119
|
url,
|
|
159
120
|
fromProtocol,
|
|
160
121
|
isCrossOrigin,
|
|
161
122
|
totalBytes: image.originalSize,
|
|
162
|
-
wastedBytes,
|
|
163
|
-
wastedWebpBytes,
|
|
123
|
+
wastedBytes: webpSavings.bytes,
|
|
164
124
|
});
|
|
165
125
|
}
|
|
166
126
|
|
|
@@ -14,7 +14,7 @@ const Sentry = require('../../lib/sentry.js');
|
|
|
14
14
|
const URL = require('../../lib/url-shim.js');
|
|
15
15
|
const i18n = require('../../lib/i18n/i18n.js');
|
|
16
16
|
const Interactive = require('../../computed/metrics/interactive.js');
|
|
17
|
-
const
|
|
17
|
+
const TraceOfTab = require('../../computed/trace-of-tab.js');
|
|
18
18
|
|
|
19
19
|
const UIStrings = {
|
|
20
20
|
/** 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. */
|
|
@@ -48,9 +48,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
48
48
|
title: str_(UIStrings.title),
|
|
49
49
|
description: str_(UIStrings.description),
|
|
50
50
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
51
|
-
|
|
52
|
-
requiredArtifacts: ['ImageElements', 'ViewportDimensions', 'GatherContext', 'devtoolsLogs',
|
|
53
|
-
'traces'],
|
|
51
|
+
requiredArtifacts: ['ImageElements', 'ViewportDimensions', 'devtoolsLogs', 'traces'],
|
|
54
52
|
};
|
|
55
53
|
}
|
|
56
54
|
|
|
@@ -183,7 +181,6 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
183
181
|
static async audit_(artifacts, networkRecords, context) {
|
|
184
182
|
const images = artifacts.ImageElements;
|
|
185
183
|
const viewportDimensions = artifacts.ViewportDimensions;
|
|
186
|
-
const gatherContext = artifacts.GatherContext;
|
|
187
184
|
const trace = artifacts.traces[ByteEfficiencyAudit.DEFAULT_PASS];
|
|
188
185
|
const devtoolsLog = artifacts.devtoolsLogs[ByteEfficiencyAudit.DEFAULT_PASS];
|
|
189
186
|
|
|
@@ -216,8 +213,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
216
213
|
const unfilteredResults = Array.from(resultsMap.values());
|
|
217
214
|
// get the interactive time or fallback to getting the end of trace time
|
|
218
215
|
try {
|
|
219
|
-
const
|
|
220
|
-
const interactive = await Interactive.request(metricComputationData, context);
|
|
216
|
+
const interactive = await Interactive.request({trace, devtoolsLog, settings}, context);
|
|
221
217
|
|
|
222
218
|
// use interactive to generate items
|
|
223
219
|
const lanternInteractive = /** @type {LH.Artifacts.LanternMetric} */ (interactive);
|
|
@@ -233,7 +229,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|
|
233
229
|
}
|
|
234
230
|
// use end of trace as a substitute for finding interactive time
|
|
235
231
|
items = OffscreenImages.filterObservedResults(unfilteredResults,
|
|
236
|
-
await
|
|
232
|
+
await TraceOfTab.request(trace, context).then(tot => tot.timestamps.traceEnd));
|
|
237
233
|
}
|
|
238
234
|
|
|
239
235
|
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
@@ -15,8 +15,7 @@ const BaseNode = require('../../lib/dependency-graph/base-node.js');
|
|
|
15
15
|
const ByteEfficiencyAudit = require('./byte-efficiency-audit.js');
|
|
16
16
|
const UnusedCSS = require('../../computed/unused-css.js');
|
|
17
17
|
const NetworkRequest = require('../../lib/network-request.js');
|
|
18
|
-
const
|
|
19
|
-
const ProcessedNavigation = require('../../computed/processed-navigation.js');
|
|
18
|
+
const TraceOfTab = require('../../computed/trace-of-tab.js');
|
|
20
19
|
const LoadSimulator = require('../../computed/load-simulator.js');
|
|
21
20
|
const FirstContentfulPaint = require('../../computed/metrics/first-contentful-paint.js');
|
|
22
21
|
|
|
@@ -113,13 +112,12 @@ class RenderBlockingResources extends Audit {
|
|
|
113
112
|
return {
|
|
114
113
|
id: 'render-blocking-resources',
|
|
115
114
|
title: str_(UIStrings.title),
|
|
116
|
-
supportedModes: ['navigation'],
|
|
117
115
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
118
116
|
description: str_(UIStrings.description),
|
|
119
117
|
// TODO: look into adding an `optionalArtifacts` property that captures the non-required nature
|
|
120
118
|
// of CSSUsage
|
|
121
119
|
requiredArtifacts: ['URL', 'TagsBlockingFirstPaint', 'traces', 'devtoolsLogs', 'CSSUsage',
|
|
122
|
-
'
|
|
120
|
+
'Stacks'],
|
|
123
121
|
};
|
|
124
122
|
}
|
|
125
123
|
|
|
@@ -129,28 +127,23 @@ class RenderBlockingResources extends Audit {
|
|
|
129
127
|
* @return {Promise<{wastedMs: number, results: Array<{url: string, totalBytes: number, wastedMs: number}>}>}
|
|
130
128
|
*/
|
|
131
129
|
static async computeResults(artifacts, context) {
|
|
132
|
-
const gatherContext = artifacts.GatherContext;
|
|
133
130
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
134
131
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
135
132
|
const simulatorData = {devtoolsLog, settings: context.settings};
|
|
136
|
-
const
|
|
137
|
-
const processedNavigation = await ProcessedNavigation.request(processedTrace, context);
|
|
133
|
+
const traceOfTab = await TraceOfTab.request(trace, context);
|
|
138
134
|
const simulator = await LoadSimulator.request(simulatorData, context);
|
|
139
135
|
const wastedCssBytes = await RenderBlockingResources.computeWastedCSSBytes(artifacts, context);
|
|
140
136
|
|
|
141
|
-
|
|
142
|
-
const metricSettings = {
|
|
143
|
-
...context.settings,
|
|
144
|
-
throttlingMethod: 'simulate',
|
|
145
|
-
};
|
|
137
|
+
const metricSettings = {throttlingMethod: 'simulate'};
|
|
146
138
|
|
|
147
|
-
|
|
148
|
-
|
|
139
|
+
/** @type {LH.Artifacts.MetricComputationData} */
|
|
140
|
+
// @ts-expect-error - TODO(bckenny): allow optional `throttling` settings
|
|
141
|
+
const metricComputationData = {trace, devtoolsLog, simulator, settings: metricSettings};
|
|
149
142
|
|
|
150
143
|
// Cast to just `LanternMetric` since we explicitly set `throttlingMethod: 'simulate'`.
|
|
151
144
|
const fcpSimulation = /** @type {LH.Artifacts.LanternMetric} */
|
|
152
145
|
(await FirstContentfulPaint.request(metricComputationData, context));
|
|
153
|
-
const fcpTsInMs =
|
|
146
|
+
const fcpTsInMs = traceOfTab.timestamps.firstContentfulPaint / 1000;
|
|
154
147
|
|
|
155
148
|
const nodesByUrl = getNodesAndTimingByUrl(fcpSimulation.optimisticEstimate.nodeTimings);
|
|
156
149
|
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const ByteEfficiencyAudit = require('./byte-efficiency-audit.js');
|
|
9
9
|
const i18n = require('../../lib/i18n/i18n.js');
|
|
10
|
-
const NetworkRequest = require('../../lib/network-request.js');
|
|
11
10
|
const NetworkRecords = require('../../computed/network-records.js');
|
|
12
11
|
|
|
13
12
|
const UIStrings = {
|
|
@@ -26,7 +25,7 @@ const UIStrings = {
|
|
|
26
25
|
|
|
27
26
|
const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);
|
|
28
27
|
|
|
29
|
-
class TotalByteWeight extends
|
|
28
|
+
class TotalByteWeight extends ByteEfficiencyAudit {
|
|
30
29
|
/**
|
|
31
30
|
* @return {LH.Audit.Meta}
|
|
32
31
|
*/
|
|
@@ -36,7 +35,7 @@ class TotalByteWeight extends Audit {
|
|
|
36
35
|
title: str_(UIStrings.title),
|
|
37
36
|
failureTitle: str_(UIStrings.failureTitle),
|
|
38
37
|
description: str_(UIStrings.description),
|
|
39
|
-
scoreDisplayMode:
|
|
38
|
+
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
40
39
|
requiredArtifacts: ['devtoolsLogs'],
|
|
41
40
|
};
|
|
42
41
|
}
|
|
@@ -60,16 +59,16 @@ class TotalByteWeight extends Audit {
|
|
|
60
59
|
* @return {Promise<LH.Audit.Product>}
|
|
61
60
|
*/
|
|
62
61
|
static async audit(artifacts, context) {
|
|
63
|
-
const devtoolsLog = artifacts.devtoolsLogs[
|
|
62
|
+
const devtoolsLog = artifacts.devtoolsLogs[ByteEfficiencyAudit.DEFAULT_PASS];
|
|
64
63
|
const records = await NetworkRecords.request(devtoolsLog, context);
|
|
65
64
|
|
|
66
65
|
let totalBytes = 0;
|
|
67
66
|
/** @type {Array<{url: string, totalBytes: number}>} */
|
|
68
67
|
let results = [];
|
|
69
68
|
records.forEach(record => {
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
if (
|
|
69
|
+
// exclude data URIs since their size is reflected in other resources
|
|
70
|
+
// exclude unfinished requests since they won't have transfer size information
|
|
71
|
+
if (record.parsedURL.scheme === 'data' || !record.finished) return;
|
|
73
72
|
|
|
74
73
|
const result = {
|
|
75
74
|
url: record.url,
|
|
@@ -84,7 +83,7 @@ class TotalByteWeight extends Audit {
|
|
|
84
83
|
itemA.url.localeCompare(itemB.url);
|
|
85
84
|
}).slice(0, 10);
|
|
86
85
|
|
|
87
|
-
const score =
|
|
86
|
+
const score = ByteEfficiencyAudit.computeLogNormalScore(
|
|
88
87
|
{p10: context.options.p10, median: context.options.median},
|
|
89
88
|
totalBytes
|
|
90
89
|
);
|
|
@@ -95,7 +94,7 @@ class TotalByteWeight extends Audit {
|
|
|
95
94
|
{key: 'totalBytes', itemType: 'bytes', text: str_(i18n.UIStrings.columnTransferSize)},
|
|
96
95
|
];
|
|
97
96
|
|
|
98
|
-
const tableDetails =
|
|
97
|
+
const tableDetails = ByteEfficiencyAudit.makeTableDetails(headings, results);
|
|
99
98
|
|
|
100
99
|
return {
|
|
101
100
|
score,
|
|
@@ -36,7 +36,7 @@ class UnminifiedCSS extends ByteEfficiencyAudit {
|
|
|
36
36
|
title: str_(UIStrings.title),
|
|
37
37
|
description: str_(UIStrings.description),
|
|
38
38
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
39
|
-
requiredArtifacts: ['CSSUsage', 'devtoolsLogs', 'traces', 'URL'
|
|
39
|
+
requiredArtifacts: ['CSSUsage', 'devtoolsLogs', 'traces', 'URL'],
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -42,7 +42,7 @@ class UnminifiedJavaScript extends ByteEfficiencyAudit {
|
|
|
42
42
|
title: str_(UIStrings.title),
|
|
43
43
|
description: str_(UIStrings.description),
|
|
44
44
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
45
|
-
requiredArtifacts: ['ScriptElements', 'devtoolsLogs', 'traces'
|
|
45
|
+
requiredArtifacts: ['ScriptElements', 'devtoolsLogs', 'traces'],
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -34,7 +34,7 @@ class UnusedCSSRules extends ByteEfficiencyAudit {
|
|
|
34
34
|
title: str_(UIStrings.title),
|
|
35
35
|
description: str_(UIStrings.description),
|
|
36
36
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
37
|
-
requiredArtifacts: ['CSSUsage', 'URL', 'devtoolsLogs', 'traces'
|
|
37
|
+
requiredArtifacts: ['CSSUsage', 'URL', 'devtoolsLogs', 'traces'],
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -67,8 +67,7 @@ class UnusedJavaScript extends ByteEfficiencyAudit {
|
|
|
67
67
|
title: str_(UIStrings.title),
|
|
68
68
|
description: str_(UIStrings.description),
|
|
69
69
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
70
|
-
requiredArtifacts: ['JsUsage', 'ScriptElements', 'SourceMaps', '
|
|
71
|
-
'devtoolsLogs', 'traces'],
|
|
70
|
+
requiredArtifacts: ['JsUsage', 'ScriptElements', 'SourceMaps', 'devtoolsLogs', 'traces'],
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
73
|
|
|
@@ -45,7 +45,7 @@ class CacheHeaders extends Audit {
|
|
|
45
45
|
failureTitle: str_(UIStrings.failureTitle),
|
|
46
46
|
description: str_(UIStrings.description),
|
|
47
47
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
48
|
-
requiredArtifacts: ['devtoolsLogs'],
|
|
48
|
+
requiredArtifacts: ['devtoolsLogs', 'traces'],
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -167,7 +167,7 @@ class CacheHeaders extends Audit {
|
|
|
167
167
|
* Returns true if headers suggest a record should not be cached for a long time.
|
|
168
168
|
* @param {Map<string, string>} headers
|
|
169
169
|
* @param {ReturnType<typeof parseCacheControl>} cacheControl
|
|
170
|
-
* @
|
|
170
|
+
* @returns {boolean}
|
|
171
171
|
*/
|
|
172
172
|
static shouldSkipRecord(headers, cacheControl) {
|
|
173
173
|
// The HTTP/1.0 Pragma header can disable caching if cache-control is not set, see https://tools.ietf.org/html/rfc7234#section-5.4
|
|
@@ -35,8 +35,7 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
|
|
|
35
35
|
title: str_(UIStrings.title),
|
|
36
36
|
description: str_(UIStrings.description),
|
|
37
37
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
38
|
-
requiredArtifacts: ['OptimizedImages', 'ImageElements', '
|
|
39
|
-
'traces', 'URL'],
|
|
38
|
+
requiredArtifacts: ['OptimizedImages', 'ImageElements', 'devtoolsLogs', 'traces', 'URL'],
|
|
40
39
|
};
|
|
41
40
|
}
|
|
42
41
|
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
16
|
const ByteEfficiencyAudit = require('./byte-efficiency-audit.js');
|
|
17
|
-
const ImageRecords = require('../../computed/image-records.js');
|
|
18
17
|
const URL = require('../../lib/url-shim.js');
|
|
19
18
|
const i18n = require('../../lib/i18n/i18n.js');
|
|
20
19
|
|
|
@@ -42,41 +41,7 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
42
41
|
title: str_(UIStrings.title),
|
|
43
42
|
description: str_(UIStrings.description),
|
|
44
43
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
45
|
-
requiredArtifacts: ['ImageElements', 'ViewportDimensions', '
|
|
46
|
-
'devtoolsLogs', 'traces'],
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @param {LH.Artifacts.ImageElement & {naturalWidth: number, naturalHeight: number}} image
|
|
52
|
-
* @param {LH.Artifacts.ViewportDimensions} ViewportDimensions
|
|
53
|
-
* @return {{width: number, height: number}};
|
|
54
|
-
*/
|
|
55
|
-
static getDisplayedDimensions(image, ViewportDimensions) {
|
|
56
|
-
if (image.displayedWidth && image.displayedHeight) {
|
|
57
|
-
return {
|
|
58
|
-
width: image.displayedWidth * ViewportDimensions.devicePixelRatio,
|
|
59
|
-
height: image.displayedHeight * ViewportDimensions.devicePixelRatio,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// If the image has 0 dimensions, it's probably hidden/offscreen, so we'll be as forgiving as possible
|
|
64
|
-
// and assume it's the size of two viewports. See https://github.com/GoogleChrome/lighthouse/issues/7236
|
|
65
|
-
const viewportWidth = ViewportDimensions.innerWidth;
|
|
66
|
-
const viewportHeight = ViewportDimensions.innerHeight * 2;
|
|
67
|
-
const imageAspectRatio = image.naturalWidth / image.naturalHeight;
|
|
68
|
-
const viewportAspectRatio = viewportWidth / viewportHeight;
|
|
69
|
-
let usedViewportWidth = viewportWidth;
|
|
70
|
-
let usedViewportHeight = viewportHeight;
|
|
71
|
-
if (imageAspectRatio > viewportAspectRatio) {
|
|
72
|
-
usedViewportHeight = viewportWidth / imageAspectRatio;
|
|
73
|
-
} else {
|
|
74
|
-
usedViewportWidth = viewportHeight * imageAspectRatio;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
width: usedViewportWidth * ViewportDimensions.devicePixelRatio,
|
|
79
|
-
height: usedViewportHeight * ViewportDimensions.devicePixelRatio,
|
|
44
|
+
requiredArtifacts: ['ImageElements', 'ViewportDimensions', 'devtoolsLogs', 'traces'],
|
|
80
45
|
};
|
|
81
46
|
}
|
|
82
47
|
|
|
@@ -93,8 +58,26 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
93
58
|
return null;
|
|
94
59
|
}
|
|
95
60
|
|
|
96
|
-
|
|
97
|
-
|
|
61
|
+
let usedPixels = image.displayedWidth * image.displayedHeight *
|
|
62
|
+
Math.pow(ViewportDimensions.devicePixelRatio, 2);
|
|
63
|
+
// If the image has 0 dimensions, it's probably hidden/offscreen, so we'll be as forgiving as possible
|
|
64
|
+
// and assume it's the size of two viewports. See https://github.com/GoogleChrome/lighthouse/issues/7236
|
|
65
|
+
if (!usedPixels) {
|
|
66
|
+
const viewportWidth = ViewportDimensions.innerWidth;
|
|
67
|
+
const viewportHeight = ViewportDimensions.innerHeight * 2;
|
|
68
|
+
const imageAspectRatio = image.naturalWidth / image.naturalHeight;
|
|
69
|
+
const viewportAspectRatio = viewportWidth / viewportHeight;
|
|
70
|
+
let usedViewportWidth = viewportWidth;
|
|
71
|
+
let usedViewportHeight = viewportHeight;
|
|
72
|
+
if (imageAspectRatio > viewportAspectRatio) {
|
|
73
|
+
usedViewportHeight = viewportWidth / imageAspectRatio;
|
|
74
|
+
} else {
|
|
75
|
+
usedViewportWidth = viewportHeight * imageAspectRatio;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
usedPixels = usedViewportWidth * usedViewportHeight *
|
|
79
|
+
Math.pow(ViewportDimensions.devicePixelRatio, 2);
|
|
80
|
+
}
|
|
98
81
|
|
|
99
82
|
const url = URL.elideDataURI(image.src);
|
|
100
83
|
const actualPixels = image.naturalWidth * image.naturalHeight;
|
|
@@ -119,14 +102,10 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
119
102
|
/**
|
|
120
103
|
* @param {LH.Artifacts} artifacts
|
|
121
104
|
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
122
|
-
* @
|
|
123
|
-
* @return {Promise<ByteEfficiencyAudit.ByteEfficiencyProduct>}
|
|
105
|
+
* @return {ByteEfficiencyAudit.ByteEfficiencyProduct}
|
|
124
106
|
*/
|
|
125
|
-
static
|
|
126
|
-
const images =
|
|
127
|
-
ImageElements: artifacts.ImageElements,
|
|
128
|
-
networkRecords,
|
|
129
|
-
}, context);
|
|
107
|
+
static audit_(artifacts, networkRecords) {
|
|
108
|
+
const images = artifacts.ImageElements;
|
|
130
109
|
const ViewportDimensions = artifacts.ViewportDimensions;
|
|
131
110
|
/** @type {Map<string, LH.Audit.ByteEfficiencyItem>} */
|
|
132
111
|
const resultsMap = new Map();
|
|
@@ -178,4 +157,3 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|
|
178
157
|
|
|
179
158
|
module.exports = UsesResponsiveImages;
|
|
180
159
|
module.exports.UIStrings = UIStrings;
|
|
181
|
-
module.exports.str_ = str_;
|
|
@@ -37,7 +37,7 @@ class ResponsesAreCompressed extends ByteEfficiencyAudit {
|
|
|
37
37
|
title: str_(UIStrings.title),
|
|
38
38
|
description: str_(UIStrings.description),
|
|
39
39
|
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
|
|
40
|
-
requiredArtifacts: ['ResponseCompression', '
|
|
40
|
+
requiredArtifacts: ['ResponseCompression', 'devtoolsLogs', 'traces'],
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -37,7 +37,6 @@ class CriticalRequestChains extends Audit {
|
|
|
37
37
|
title: str_(UIStrings.title),
|
|
38
38
|
description: str_(UIStrings.description),
|
|
39
39
|
scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
|
|
40
|
-
supportedModes: ['navigation'],
|
|
41
40
|
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL'],
|
|
42
41
|
};
|
|
43
42
|
}
|
|
@@ -21,7 +21,7 @@ const UIStrings = {
|
|
|
21
21
|
/** Description of a Lighthouse audit that evaluates the security of a page's CSP. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. "CSP" stands for "Content Security Policy". "XSS" stands for "Cross Site Scripting". "CSP" and "XSS" do not need to be translated. */
|
|
22
22
|
description: 'A strong Content Security Policy (CSP) significantly ' +
|
|
23
23
|
'reduces the risk of cross-site scripting (XSS) attacks. ' +
|
|
24
|
-
'[Learn more](https://web.dev/csp
|
|
24
|
+
'[Learn more](https://web.dev/strict-csp/)',
|
|
25
25
|
/** Summary text for the results of a Lighthouse audit that evaluates the security of a page's CSP. This is displayed if no CSP is being enforced. "CSP" stands for "Content Security Policy". "CSP" does not need to be translated. */
|
|
26
26
|
noCsp: 'No CSP found in enforcement mode',
|
|
27
27
|
/** Message shown when one or more CSPs are defined in a <meta> tag. Shown in a table with a list of other CSP bypasses and warnings. "CSP" stands for "Content Security Policy". "CSP" and "HTTP" do not need to be translated. */
|
|
@@ -37,7 +37,6 @@ class GeolocationOnStart extends ViolationAudit {
|
|
|
37
37
|
title: str_(UIStrings.title),
|
|
38
38
|
failureTitle: str_(UIStrings.failureTitle),
|
|
39
39
|
description: str_(UIStrings.description),
|
|
40
|
-
supportedModes: ['navigation'],
|
|
41
40
|
requiredArtifacts: ['ConsoleMessages'],
|
|
42
41
|
};
|
|
43
42
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* @fileoverview Audits a page to determine whether it generates issues in the Issues panel of Chrome Devtools.
|
|
9
9
|
* The audit is meant to maintain parity with the Chrome Devtools Issues panel front end.
|
|
10
|
-
* https://source.chromium.org/chromium/chromium/src/+/
|
|
10
|
+
* https://source.chromium.org/chromium/chromium/src/+/master:third_party/devtools-frontend/src/front_end/sdk/
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
@@ -37,7 +37,6 @@ class NotificationOnStart extends ViolationAudit {
|
|
|
37
37
|
title: str_(UIStrings.title),
|
|
38
38
|
failureTitle: str_(UIStrings.failureTitle),
|
|
39
39
|
description: str_(UIStrings.description),
|
|
40
|
-
supportedModes: ['navigation'],
|
|
41
40
|
requiredArtifacts: ['ConsoleMessages'],
|
|
42
41
|
};
|
|
43
42
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const Audit = require('./audit.js');
|
|
9
9
|
const LHError = require('../lib/lh-error.js');
|
|
10
|
-
const
|
|
10
|
+
const TraceOfTab = require('../computed/trace-of-tab.js');
|
|
11
11
|
const Screenshots = require('../computed/screenshots.js');
|
|
12
12
|
|
|
13
13
|
class FinalScreenshot extends Audit {
|
|
@@ -20,7 +20,7 @@ class FinalScreenshot extends Audit {
|
|
|
20
20
|
scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
|
|
21
21
|
title: 'Final Screenshot',
|
|
22
22
|
description: 'The last screenshot captured of the pageload.',
|
|
23
|
-
requiredArtifacts: ['traces'
|
|
23
|
+
requiredArtifacts: ['traces'],
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -31,16 +31,12 @@ class FinalScreenshot extends Audit {
|
|
|
31
31
|
*/
|
|
32
32
|
static async audit(artifacts, context) {
|
|
33
33
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
34
|
-
const
|
|
34
|
+
const traceOfTab = await TraceOfTab.request(trace, context);
|
|
35
35
|
const screenshots = await Screenshots.request(trace, context);
|
|
36
|
-
const {timeOrigin} =
|
|
36
|
+
const {timeOrigin} = traceOfTab.timestamps;
|
|
37
37
|
const finalScreenshot = screenshots[screenshots.length - 1];
|
|
38
38
|
|
|
39
39
|
if (!finalScreenshot) {
|
|
40
|
-
// If a timespan didn't happen to contain frames, that's fine. Just mark not applicable.
|
|
41
|
-
if (artifacts.GatherContext.gatherMode === 'timespan') return {notApplicable: true, score: 1};
|
|
42
|
-
|
|
43
|
-
// If it was another mode, that's a fatal error.
|
|
44
40
|
throw new LHError(LHError.errors.NO_SCREENSHOTS);
|
|
45
41
|
}
|
|
46
42
|
|
|
@@ -48,7 +48,6 @@ class FontDisplay extends Audit {
|
|
|
48
48
|
title: str_(UIStrings.title),
|
|
49
49
|
failureTitle: str_(UIStrings.failureTitle),
|
|
50
50
|
description: str_(UIStrings.description),
|
|
51
|
-
supportedModes: ['navigation'],
|
|
52
51
|
requiredArtifacts: ['devtoolsLogs', 'CSSUsage', 'URL'],
|
|
53
52
|
};
|
|
54
53
|
}
|