lighthouse 12.8.2 → 13.0.0-dev.20251009
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 +1 -1
- package/cli/test/smokehouse/config/exclusions.js +0 -2
- package/cli/test/smokehouse/version-check.d.ts +1 -1
- package/core/audits/accessibility/accesskeys.js +3 -3
- package/core/audits/accessibility/aria-allowed-attr.js +3 -3
- package/core/audits/accessibility/aria-allowed-role.js +2 -1
- package/core/audits/accessibility/aria-command-name.js +1 -1
- package/core/audits/accessibility/aria-conditional-attr.js +1 -1
- package/core/audits/accessibility/aria-deprecated-role.js +1 -1
- package/core/audits/accessibility/aria-dialog-name.js +1 -1
- package/core/audits/accessibility/aria-hidden-body.js +3 -3
- package/core/audits/accessibility/aria-hidden-focus.js +3 -3
- package/core/audits/accessibility/aria-input-field-name.js +3 -3
- package/core/audits/accessibility/aria-meter-name.js +1 -1
- package/core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/core/audits/accessibility/aria-prohibited-attr.js +1 -1
- package/core/audits/accessibility/aria-required-attr.js +3 -3
- package/core/audits/accessibility/aria-required-children.js +3 -3
- package/core/audits/accessibility/aria-required-parent.js +3 -3
- package/core/audits/accessibility/aria-roles.js +3 -3
- package/core/audits/accessibility/aria-text.js +3 -3
- package/core/audits/accessibility/aria-toggle-field-name.js +3 -3
- package/core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/core/audits/accessibility/aria-valid-attr-value.js +3 -3
- package/core/audits/accessibility/aria-valid-attr.js +3 -3
- package/core/audits/accessibility/button-name.js +3 -3
- package/core/audits/accessibility/bypass.js +3 -3
- package/core/audits/accessibility/color-contrast.js +3 -3
- package/core/audits/accessibility/definition-list.js +3 -3
- package/core/audits/accessibility/dlitem.js +3 -3
- package/core/audits/accessibility/document-title.js +3 -3
- package/core/audits/accessibility/duplicate-id-aria.js +3 -3
- package/core/audits/accessibility/empty-heading.js +3 -3
- package/core/audits/accessibility/form-field-multiple-labels.js +3 -3
- package/core/audits/accessibility/frame-title.js +3 -3
- package/core/audits/accessibility/heading-order.js +3 -3
- package/core/audits/accessibility/html-has-lang.js +3 -3
- package/core/audits/accessibility/html-lang-valid.js +3 -3
- package/core/audits/accessibility/html-xml-lang-mismatch.js +3 -3
- package/core/audits/accessibility/identical-links-same-purpose.js +3 -3
- package/core/audits/accessibility/image-alt.js +3 -3
- package/core/audits/accessibility/image-redundant-alt.js +4 -3
- package/core/audits/accessibility/input-button-name.js +3 -3
- package/core/audits/accessibility/input-image-alt.js +3 -3
- package/core/audits/accessibility/label-content-name-mismatch.js +3 -3
- package/core/audits/accessibility/label.js +3 -3
- package/core/audits/accessibility/landmark-one-main.js +3 -4
- package/core/audits/accessibility/link-in-text-block.js +3 -3
- package/core/audits/accessibility/link-name.js +3 -3
- package/core/audits/accessibility/list.js +3 -3
- package/core/audits/accessibility/listitem.js +3 -3
- package/core/audits/accessibility/meta-refresh.js +3 -3
- package/core/audits/accessibility/meta-viewport.js +3 -3
- package/core/audits/accessibility/object-alt.js +3 -3
- package/core/audits/accessibility/select-name.js +3 -3
- package/core/audits/accessibility/skip-link.js +3 -3
- package/core/audits/accessibility/tabindex.js +3 -3
- package/core/audits/accessibility/table-duplicate-name.js +4 -3
- package/core/audits/accessibility/table-fake-caption.js +3 -3
- package/core/audits/accessibility/target-size.js +3 -3
- package/core/audits/accessibility/td-has-header.js +3 -3
- package/core/audits/accessibility/td-headers-attr.js +3 -3
- package/core/audits/accessibility/th-has-data-cells.js +3 -3
- package/core/audits/accessibility/valid-lang.js +3 -3
- package/core/audits/accessibility/video-caption.js +3 -3
- package/core/audits/audit.d.ts +0 -4
- package/core/audits/audit.js +2 -13
- package/core/audits/insights/cls-culprits-insight.js +1 -1
- package/core/audits/insights/dom-size-insight.js +11 -7
- package/core/audits/insights/font-display-insight.js +3 -1
- package/core/audits/insights/image-delivery-insight.js +4 -1
- package/core/audits/insights/insight-audit.d.ts +6 -4
- package/core/audits/insights/insight-audit.js +27 -8
- package/core/audits/insights/third-parties-insight.js +1 -1
- package/core/audits/layout-shifts.js +1 -1
- package/core/audits/predictive-perf.js +2 -2
- package/core/audits/seo/crawlable-anchors.js +2 -3
- package/core/audits/seo/manual/structured-data.js +1 -1
- package/core/audits/server-response-time.d.ts +0 -5
- package/core/audits/server-response-time.js +12 -26
- package/core/computed/metrics/cumulative-layout-shift.js +2 -2
- package/core/computed/metrics/lantern-metric.js +3 -3
- package/core/computed/metrics/lcp-breakdown.d.ts +10 -5
- package/core/computed/metrics/lcp-breakdown.js +50 -22
- package/core/computed/metrics/time-to-first-byte.js +33 -10
- package/core/computed/metrics/timing-summary.js +3 -2
- package/core/computed/page-dependency-graph.js +1 -1
- package/core/computed/trace-engine-result.js +2 -2
- package/core/config/default-config.js +110 -152
- package/core/config/experimental-config.js +1 -32
- package/core/config/filters.js +6 -9
- package/core/config/lr-desktop-config.js +0 -1
- package/core/config/lr-mobile-config.js +0 -1
- package/core/gather/driver/target-manager.d.ts +1 -1
- package/core/gather/driver.d.ts +1 -1
- package/core/gather/gatherers/anchor-elements.js +8 -24
- package/core/gather/gatherers/image-elements.js +32 -6
- package/core/gather/gatherers/inspector-issues.js +1 -28
- package/core/gather/gatherers/trace-elements.d.ts +2 -11
- package/core/gather/gatherers/trace-elements.js +9 -39
- package/core/gather/navigation-runner.js +0 -3
- package/core/gather/session.d.ts +1 -1
- package/core/lib/asset-saver.d.ts +2 -2
- package/core/lib/asset-saver.js +33 -43
- package/core/lib/bf-cache-strings.js +10 -9
- package/core/lib/deprecations-strings.js +5 -5
- package/core/lib/emulation.d.ts +10 -0
- package/core/lib/emulation.js +21 -6
- package/core/lib/legacy-javascript/legacy-javascript.js +4 -11
- package/core/lib/network-request.d.ts +0 -7
- package/core/lib/network-request.js +0 -16
- package/core/lib/proto-preprocessor.js +10 -25
- package/core/runner.js +1 -8
- package/core/scoring.js +1 -1
- package/dist/report/bundle.esm.js +10 -49
- package/dist/report/flow.js +12 -51
- package/dist/report/standalone.js +11 -50
- package/flow-report/src/i18n/i18n.d.ts +4 -6
- package/package.json +16 -19
- package/readme.md +2 -2
- package/report/assets/styles.css +0 -39
- package/report/renderer/api.js +0 -1
- package/report/renderer/category-renderer.js +6 -0
- package/report/renderer/components.js +1 -1
- package/report/renderer/details-renderer.d.ts +1 -2
- package/report/renderer/details-renderer.js +0 -1
- package/report/renderer/dom.d.ts +0 -13
- package/report/renderer/dom.js +0 -38
- package/report/renderer/performance-category-renderer.d.ts +0 -26
- package/report/renderer/performance-category-renderer.js +10 -142
- package/report/renderer/report-ui-features.d.ts +0 -1
- package/report/renderer/report-ui-features.js +2 -13
- package/report/renderer/report-utils.d.ts +2 -3
- package/report/renderer/report-utils.js +4 -6
- package/report/types/report-renderer.d.ts +0 -6
- package/shared/localization/locales/ar-XB.json +107 -455
- package/shared/localization/locales/ar.json +107 -455
- package/shared/localization/locales/bg.json +96 -444
- package/shared/localization/locales/ca.json +96 -444
- package/shared/localization/locales/cs.json +96 -444
- package/shared/localization/locales/da.json +96 -444
- package/shared/localization/locales/de.json +96 -444
- package/shared/localization/locales/el.json +96 -444
- package/shared/localization/locales/en-GB.json +96 -444
- package/shared/localization/locales/en-US.json +116 -467
- package/shared/localization/locales/en-XA.json +93 -441
- package/shared/localization/locales/en-XL.json +116 -467
- package/shared/localization/locales/es-419.json +96 -444
- package/shared/localization/locales/es.json +96 -444
- package/shared/localization/locales/fi.json +96 -444
- package/shared/localization/locales/fil.json +96 -444
- package/shared/localization/locales/fr.json +96 -444
- package/shared/localization/locales/he.json +118 -466
- package/shared/localization/locales/hi.json +96 -444
- package/shared/localization/locales/hr.json +100 -448
- package/shared/localization/locales/hu.json +96 -444
- package/shared/localization/locales/id.json +96 -444
- package/shared/localization/locales/it.json +96 -444
- package/shared/localization/locales/ja.json +96 -444
- package/shared/localization/locales/ko.json +97 -445
- package/shared/localization/locales/lt.json +96 -444
- package/shared/localization/locales/lv.json +97 -445
- package/shared/localization/locales/nl.json +96 -444
- package/shared/localization/locales/no.json +96 -444
- package/shared/localization/locales/pl.json +96 -444
- package/shared/localization/locales/pt-PT.json +96 -444
- package/shared/localization/locales/pt.json +97 -445
- package/shared/localization/locales/ro.json +97 -445
- package/shared/localization/locales/ru.json +96 -444
- package/shared/localization/locales/sk.json +96 -444
- package/shared/localization/locales/sl.json +96 -444
- package/shared/localization/locales/sr-Latn.json +96 -444
- package/shared/localization/locales/sr.json +96 -444
- package/shared/localization/locales/sv.json +96 -444
- package/shared/localization/locales/ta.json +96 -444
- package/shared/localization/locales/te.json +97 -445
- package/shared/localization/locales/th.json +96 -444
- package/shared/localization/locales/tr.json +96 -444
- package/shared/localization/locales/uk.json +96 -444
- package/shared/localization/locales/vi.json +96 -444
- package/shared/localization/locales/zh-HK.json +96 -444
- package/shared/localization/locales/zh-TW.json +97 -445
- package/shared/localization/locales/zh.json +96 -444
- package/shared/localization/locales.d.ts +2 -0
- package/shared/localization/locales.js +130 -139
- package/shared/tsconfig.json +2 -0
- package/tsconfig-base.json +2 -2
- package/tsconfig.json +1 -4
- package/types/artifacts.d.ts +6 -81
- package/types/audit.d.ts +1 -1
- package/types/lhr/settings.d.ts +1 -1
- package/core/audits/byte-efficiency/duplicated-javascript.d.ts +0 -45
- package/core/audits/byte-efficiency/duplicated-javascript.js +0 -223
- package/core/audits/byte-efficiency/efficient-animated-content.d.ts +0 -22
- package/core/audits/byte-efficiency/efficient-animated-content.js +0 -93
- package/core/audits/byte-efficiency/legacy-javascript.d.ts +0 -28
- package/core/audits/byte-efficiency/legacy-javascript.js +0 -144
- package/core/audits/byte-efficiency/modern-image-formats.d.ts +0 -38
- package/core/audits/byte-efficiency/modern-image-formats.js +0 -187
- package/core/audits/byte-efficiency/offscreen-images.d.ts +0 -63
- package/core/audits/byte-efficiency/offscreen-images.js +0 -240
- package/core/audits/byte-efficiency/render-blocking-resources.d.ts +0 -53
- package/core/audits/byte-efficiency/render-blocking-resources.js +0 -312
- package/core/audits/byte-efficiency/uses-long-cache-ttl.d.ts +0 -59
- package/core/audits/byte-efficiency/uses-long-cache-ttl.js +0 -293
- package/core/audits/byte-efficiency/uses-optimized-images.d.ts +0 -33
- package/core/audits/byte-efficiency/uses-optimized-images.js +0 -146
- package/core/audits/byte-efficiency/uses-responsive-images-snapshot.d.ts +0 -16
- package/core/audits/byte-efficiency/uses-responsive-images-snapshot.js +0 -106
- package/core/audits/byte-efficiency/uses-responsive-images.d.ts +0 -44
- package/core/audits/byte-efficiency/uses-responsive-images.js +0 -202
- package/core/audits/byte-efficiency/uses-text-compression.d.ts +0 -14
- package/core/audits/byte-efficiency/uses-text-compression.js +0 -108
- package/core/audits/critical-request-chains.d.ts +0 -44
- package/core/audits/critical-request-chains.js +0 -221
- package/core/audits/dobetterweb/dom-size.d.ts +0 -32
- package/core/audits/dobetterweb/dom-size.js +0 -182
- package/core/audits/dobetterweb/no-document-write.d.ts +0 -16
- package/core/audits/dobetterweb/no-document-write.js +0 -86
- package/core/audits/dobetterweb/uses-http2.d.ts +0 -72
- package/core/audits/dobetterweb/uses-http2.js +0 -276
- package/core/audits/dobetterweb/uses-passive-event-listeners.d.ts +0 -16
- package/core/audits/dobetterweb/uses-passive-event-listeners.js +0 -69
- package/core/audits/font-display.d.ts +0 -32
- package/core/audits/font-display.js +0 -195
- package/core/audits/largest-contentful-paint-element.d.ts +0 -34
- package/core/audits/largest-contentful-paint-element.js +0 -181
- package/core/audits/lcp-lazy-loaded.d.ts +0 -22
- package/core/audits/lcp-lazy-loaded.js +0 -115
- package/core/audits/metrics/first-meaningful-paint.d.ts +0 -12
- package/core/audits/metrics/first-meaningful-paint.js +0 -47
- package/core/audits/preload-fonts.d.ts +0 -25
- package/core/audits/preload-fonts.js +0 -97
- package/core/audits/prioritize-lcp-image.d.ts +0 -74
- package/core/audits/prioritize-lcp-image.js +0 -297
- package/core/audits/seo/font-size.d.ts +0 -24
- package/core/audits/seo/font-size.js +0 -344
- package/core/audits/third-party-facades.d.ts +0 -41
- package/core/audits/third-party-facades.js +0 -234
- package/core/audits/third-party-summary.d.ts +0 -78
- package/core/audits/third-party-summary.js +0 -236
- package/core/audits/uses-rel-preconnect.d.ts +0 -37
- package/core/audits/uses-rel-preconnect.js +0 -286
- package/core/audits/uses-rel-preload.d.ts +0 -57
- package/core/audits/uses-rel-preload.js +0 -263
- package/core/audits/viewport.d.ts +0 -17
- package/core/audits/viewport.js +0 -87
- package/core/audits/work-during-interaction.d.ts +0 -81
- package/core/audits/work-during-interaction.js +0 -287
- package/core/computed/critical-request-chains.d.ts +0 -42
- package/core/computed/critical-request-chains.js +0 -143
- package/core/computed/viewport-meta.d.ts +0 -37
- package/core/computed/viewport-meta.js +0 -71
- package/core/gather/gatherers/cache-contents.d.ts +0 -11
- package/core/gather/gatherers/cache-contents.js +0 -56
- package/core/gather/gatherers/devtools-log-compat.d.ts +0 -13
- package/core/gather/gatherers/devtools-log-compat.js +0 -35
- package/core/gather/gatherers/dobetterweb/domstats.d.ts +0 -10
- package/core/gather/gatherers/dobetterweb/domstats.js +0 -102
- package/core/gather/gatherers/dobetterweb/optimized-images.d.ts +0 -48
- package/core/gather/gatherers/dobetterweb/optimized-images.js +0 -169
- package/core/gather/gatherers/dobetterweb/response-compression.d.ts +0 -23
- package/core/gather/gatherers/dobetterweb/response-compression.js +0 -136
- package/core/gather/gatherers/seo/font-size.d.ts +0 -131
- package/core/gather/gatherers/seo/font-size.js +0 -347
- package/core/gather/gatherers/trace-compat.d.ts +0 -13
- package/core/gather/gatherers/trace-compat.js +0 -35
- package/types/internal/metaviewport-parser.d.ts +0 -13
- package/types/internal/parse-cache-control.d.ts +0 -20
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2017 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
/*
|
|
7
|
-
* @fileoverview This audit determines if the images could be smaller when compressed with WebP.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
12
|
-
import UrlUtils from '../../lib/url-utils.js';
|
|
13
|
-
import * as i18n from '../../lib/i18n/i18n.js';
|
|
14
|
-
|
|
15
|
-
const UIStrings = {
|
|
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
|
-
title: 'Serve images in next-gen formats',
|
|
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. The last sentence starting with 'Learn' becomes link text to additional documentation. */
|
|
19
|
-
description: 'Image formats like WebP and AVIF often provide better ' +
|
|
20
|
-
'compression than PNG or JPEG, which means faster downloads and less data consumption. ' +
|
|
21
|
-
'[Learn more about modern image formats](https://developer.chrome.com/docs/lighthouse/performance/uses-webp-images/).',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
25
|
-
|
|
26
|
-
const IGNORE_THRESHOLD_IN_BYTES = 8192;
|
|
27
|
-
|
|
28
|
-
class ModernImageFormats extends ByteEfficiencyAudit {
|
|
29
|
-
/**
|
|
30
|
-
* @return {LH.Audit.Meta}
|
|
31
|
-
*/
|
|
32
|
-
static get meta() {
|
|
33
|
-
return {
|
|
34
|
-
id: 'modern-image-formats',
|
|
35
|
-
title: str_(UIStrings.title),
|
|
36
|
-
description: str_(UIStrings.description),
|
|
37
|
-
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
|
|
38
|
-
guidanceLevel: 3,
|
|
39
|
-
requiredArtifacts: ['OptimizedImages', 'DevtoolsLog', 'Trace', 'URL', 'GatherContext',
|
|
40
|
-
'ImageElements', 'SourceMaps'],
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @param {{naturalWidth: number, naturalHeight: number}} imageElement
|
|
46
|
-
* @return {number}
|
|
47
|
-
*/
|
|
48
|
-
static estimateWebPSizeFromDimensions(imageElement) {
|
|
49
|
-
const totalPixels = imageElement.naturalWidth * imageElement.naturalHeight;
|
|
50
|
-
// See uses-optimized-images for the rationale behind our 2 byte-per-pixel baseline and
|
|
51
|
-
// JPEG compression ratio of 8:1.
|
|
52
|
-
// WebP usually gives ~20% additional savings on top of that, so we will use 10:1.
|
|
53
|
-
// This is quite pessimistic as their study shows a photographic compression ratio of ~29:1.
|
|
54
|
-
// https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study#results
|
|
55
|
-
const expectedBytesPerPixel = 2 * 1 / 10;
|
|
56
|
-
return Math.round(totalPixels * expectedBytesPerPixel);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @param {{naturalWidth: number, naturalHeight: number}} imageElement
|
|
61
|
-
* @return {number}
|
|
62
|
-
*/
|
|
63
|
-
static estimateAvifSizeFromDimensions(imageElement) {
|
|
64
|
-
const totalPixels = imageElement.naturalWidth * imageElement.naturalHeight;
|
|
65
|
-
// See above for the rationale behind our 2 byte-per-pixel baseline and WebP ratio of 10:1.
|
|
66
|
-
// AVIF usually gives ~20% additional savings on top of that, so we will use 12:1.
|
|
67
|
-
// This is quite pessimistic as Netflix study shows a photographic compression ratio of ~40:1
|
|
68
|
-
// (0.4 *bits* per pixel at SSIM 0.97).
|
|
69
|
-
// https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4
|
|
70
|
-
const expectedBytesPerPixel = 2 * 1 / 12;
|
|
71
|
-
return Math.round(totalPixels * expectedBytesPerPixel);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @param {{jpegSize: number | undefined, webpSize: number | undefined}} otherFormatSizes
|
|
76
|
-
* @return {number|undefined}
|
|
77
|
-
*/
|
|
78
|
-
static estimateAvifSizeFromWebPAndJpegEstimates(otherFormatSizes) {
|
|
79
|
-
if (!otherFormatSizes.jpegSize || !otherFormatSizes.webpSize) return undefined;
|
|
80
|
-
|
|
81
|
-
// AVIF saves at least ~50% on JPEG, ~20% on WebP at low quality.
|
|
82
|
-
// http://downloads.aomedia.org/assets/pdf/symposium-2019/slides/CyrilConcolato_Netflix-AVIF-AOM-Research-Symposium-2019.pdf
|
|
83
|
-
// https://jakearchibald.com/2020/avif-has-landed/
|
|
84
|
-
// https://www.finally.agency/blog/what-is-avif-image-format
|
|
85
|
-
// See https://github.com/GoogleChrome/lighthouse/issues/12295#issue-840261460 for more.
|
|
86
|
-
const estimateFromJpeg = otherFormatSizes.jpegSize * 5 / 10;
|
|
87
|
-
const estimateFromWebp = otherFormatSizes.webpSize * 8 / 10;
|
|
88
|
-
return estimateFromJpeg / 2 + estimateFromWebp / 2;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @param {LH.Artifacts} artifacts
|
|
93
|
-
* @return {import('./byte-efficiency-audit.js').ByteEfficiencyProduct}
|
|
94
|
-
*/
|
|
95
|
-
static audit_(artifacts) {
|
|
96
|
-
const pageURL = artifacts.URL.finalDisplayedUrl;
|
|
97
|
-
const images = artifacts.OptimizedImages;
|
|
98
|
-
const imageElements = artifacts.ImageElements;
|
|
99
|
-
/** @type {Map<string, LH.Artifacts.ImageElement>} */
|
|
100
|
-
const imageElementsByURL = new Map();
|
|
101
|
-
imageElements.forEach(img => imageElementsByURL.set(img.src, img));
|
|
102
|
-
|
|
103
|
-
/** @type {Array<LH.Audit.ByteEfficiencyItem>} */
|
|
104
|
-
const items = [];
|
|
105
|
-
const warnings = [];
|
|
106
|
-
for (const image of images) {
|
|
107
|
-
const imageElement = imageElementsByURL.get(image.url);
|
|
108
|
-
|
|
109
|
-
if (image.failed) {
|
|
110
|
-
warnings.push(`Unable to decode ${UrlUtils.getURLDisplayName(image.url)}`);
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Skip if the image was already using a modern format.
|
|
115
|
-
if (image.mimeType === 'image/webp' || image.mimeType === 'image/avif') continue;
|
|
116
|
-
|
|
117
|
-
const jpegSize = image.jpegSize;
|
|
118
|
-
let webpSize = image.webpSize;
|
|
119
|
-
let avifSize = ModernImageFormats.estimateAvifSizeFromWebPAndJpegEstimates({
|
|
120
|
-
jpegSize,
|
|
121
|
-
webpSize,
|
|
122
|
-
});
|
|
123
|
-
let fromProtocol = true;
|
|
124
|
-
|
|
125
|
-
if (typeof webpSize === 'undefined') {
|
|
126
|
-
if (!imageElement) {
|
|
127
|
-
warnings.push(`Unable to locate resource ${UrlUtils.getURLDisplayName(image.url)}`);
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Skip if we couldn't collect natural image size information.
|
|
132
|
-
if (!imageElement.naturalDimensions) continue;
|
|
133
|
-
const naturalHeight = imageElement.naturalDimensions.height;
|
|
134
|
-
const naturalWidth = imageElement.naturalDimensions.width;
|
|
135
|
-
// If naturalHeight or naturalWidth are falsy, information is not valid, skip.
|
|
136
|
-
if (!naturalWidth || !naturalHeight) continue;
|
|
137
|
-
|
|
138
|
-
webpSize = ModernImageFormats.estimateWebPSizeFromDimensions({
|
|
139
|
-
naturalHeight,
|
|
140
|
-
naturalWidth,
|
|
141
|
-
});
|
|
142
|
-
avifSize = ModernImageFormats.estimateAvifSizeFromDimensions({
|
|
143
|
-
naturalHeight,
|
|
144
|
-
naturalWidth,
|
|
145
|
-
});
|
|
146
|
-
fromProtocol = false;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (webpSize === undefined || avifSize === undefined) continue;
|
|
150
|
-
|
|
151
|
-
// Visible wasted bytes uses AVIF, but we still include the WebP savings in the LHR.
|
|
152
|
-
const wastedWebpBytes = image.originalSize - webpSize;
|
|
153
|
-
const wastedBytes = image.originalSize - avifSize;
|
|
154
|
-
if (wastedBytes < IGNORE_THRESHOLD_IN_BYTES) continue;
|
|
155
|
-
|
|
156
|
-
const url = UrlUtils.elideDataURI(image.url);
|
|
157
|
-
const isCrossOrigin = !UrlUtils.originsMatch(pageURL, image.url);
|
|
158
|
-
|
|
159
|
-
items.push({
|
|
160
|
-
node: imageElement ? ByteEfficiencyAudit.makeNodeItem(imageElement.node) : undefined,
|
|
161
|
-
url,
|
|
162
|
-
fromProtocol,
|
|
163
|
-
isCrossOrigin,
|
|
164
|
-
totalBytes: image.originalSize,
|
|
165
|
-
wastedBytes,
|
|
166
|
-
wastedWebpBytes,
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
171
|
-
const headings = [
|
|
172
|
-
{key: 'node', valueType: 'node', label: ''},
|
|
173
|
-
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
174
|
-
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnResourceSize)},
|
|
175
|
-
{key: 'wastedBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnWastedBytes)},
|
|
176
|
-
];
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
warnings,
|
|
180
|
-
items,
|
|
181
|
-
headings,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export default ModernImageFormats;
|
|
187
|
-
export {UIStrings};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export default OffscreenImages;
|
|
2
|
-
export type WasteResult = {
|
|
3
|
-
node: LH.Audit.Details.NodeValue;
|
|
4
|
-
url: string;
|
|
5
|
-
requestStartTime: number;
|
|
6
|
-
totalBytes: number;
|
|
7
|
-
wastedBytes: number;
|
|
8
|
-
wastedPercent: number;
|
|
9
|
-
};
|
|
10
|
-
/** @typedef {{node: LH.Audit.Details.NodeValue, url: string, requestStartTime: number, totalBytes: number, wastedBytes: number, wastedPercent: number}} WasteResult */
|
|
11
|
-
declare class OffscreenImages extends ByteEfficiencyAudit {
|
|
12
|
-
/**
|
|
13
|
-
* @param {{top: number, bottom: number, left: number, right: number}} imageRect
|
|
14
|
-
* @param {{innerWidth: number, innerHeight: number}} viewportDimensions
|
|
15
|
-
* @return {number}
|
|
16
|
-
*/
|
|
17
|
-
static computeVisiblePixels(imageRect: {
|
|
18
|
-
top: number;
|
|
19
|
-
bottom: number;
|
|
20
|
-
left: number;
|
|
21
|
-
right: number;
|
|
22
|
-
}, viewportDimensions: {
|
|
23
|
-
innerWidth: number;
|
|
24
|
-
innerHeight: number;
|
|
25
|
-
}): number;
|
|
26
|
-
/**
|
|
27
|
-
* @param {LH.Artifacts.ImageElement} image
|
|
28
|
-
* @param {{innerWidth: number, innerHeight: number}} viewportDimensions
|
|
29
|
-
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
30
|
-
* @return {null|Error|WasteResult}
|
|
31
|
-
*/
|
|
32
|
-
static computeWaste(image: LH.Artifacts.ImageElement, viewportDimensions: {
|
|
33
|
-
innerWidth: number;
|
|
34
|
-
innerHeight: number;
|
|
35
|
-
}, networkRecords: Array<LH.Artifacts.NetworkRequest>): null | Error | WasteResult;
|
|
36
|
-
/**
|
|
37
|
-
* Filters out image requests that were requested after the last long task based on lantern timings.
|
|
38
|
-
*
|
|
39
|
-
* @param {WasteResult[]} images
|
|
40
|
-
* @param {LH.Artifacts.LanternMetric} lanternMetricData
|
|
41
|
-
*/
|
|
42
|
-
static filterLanternResults(images: WasteResult[], lanternMetricData: LH.Artifacts.LanternMetric): WasteResult[];
|
|
43
|
-
/**
|
|
44
|
-
* Filters out image requests that were requested after TTI.
|
|
45
|
-
*
|
|
46
|
-
* @param {WasteResult[]} images
|
|
47
|
-
* @param {number} interactiveTimestamp
|
|
48
|
-
*/
|
|
49
|
-
static filterObservedResults(images: WasteResult[], interactiveTimestamp: number): WasteResult[];
|
|
50
|
-
/**
|
|
51
|
-
* @param {LH.Artifacts} artifacts
|
|
52
|
-
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
53
|
-
* @param {LH.Audit.Context} context
|
|
54
|
-
* @return {Promise<import('./byte-efficiency-audit.js').ByteEfficiencyProduct>}
|
|
55
|
-
*/
|
|
56
|
-
static audit_(artifacts: LH.Artifacts, networkRecords: Array<LH.Artifacts.NetworkRequest>, context: LH.Audit.Context): Promise<import("./byte-efficiency-audit.js").ByteEfficiencyProduct>;
|
|
57
|
-
}
|
|
58
|
-
export namespace UIStrings {
|
|
59
|
-
let title: string;
|
|
60
|
-
let description: string;
|
|
61
|
-
}
|
|
62
|
-
import { ByteEfficiencyAudit } from './byte-efficiency-audit.js';
|
|
63
|
-
//# sourceMappingURL=offscreen-images.d.ts.map
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2017 Google LLC
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* @fileoverview Checks to see if images are displayed only outside of the viewport.
|
|
8
|
-
* Images requested after TTI are not flagged as violations.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import {ByteEfficiencyAudit} from './byte-efficiency-audit.js';
|
|
13
|
-
import {NetworkRequest} from '../../lib/network-request.js';
|
|
14
|
-
import {Sentry} from '../../lib/sentry.js';
|
|
15
|
-
import UrlUtils from '../../lib/url-utils.js';
|
|
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';
|
|
19
|
-
|
|
20
|
-
const UIStrings = {
|
|
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. */
|
|
22
|
-
title: 'Defer offscreen images',
|
|
23
|
-
/** Description of a Lighthouse audit that tells the user *why* they should 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 after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
|
|
24
|
-
description:
|
|
25
|
-
'Consider lazy-loading offscreen and hidden images after all critical resources have ' +
|
|
26
|
-
'finished loading to lower time to interactive. ' +
|
|
27
|
-
'[Learn how to defer offscreen images](https://developer.chrome.com/docs/lighthouse/performance/offscreen-images/).',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
31
|
-
|
|
32
|
-
// See https://github.com/GoogleChrome/lighthouse/issues/10471 for discussion about the thresholds here.
|
|
33
|
-
const ALLOWABLE_OFFSCREEN_IN_PX = 100;
|
|
34
|
-
const ALLOWABLE_OFFSCREEN_BOTTOM_IN_VIEWPORTS = 3;
|
|
35
|
-
|
|
36
|
-
const IGNORE_THRESHOLD_IN_BYTES = 2048;
|
|
37
|
-
const IGNORE_THRESHOLD_IN_PERCENT = 75;
|
|
38
|
-
const IGNORE_THRESHOLD_IN_MS = 50;
|
|
39
|
-
|
|
40
|
-
/** @typedef {{node: LH.Audit.Details.NodeValue, url: string, requestStartTime: number, totalBytes: number, wastedBytes: number, wastedPercent: number}} WasteResult */
|
|
41
|
-
|
|
42
|
-
class OffscreenImages extends ByteEfficiencyAudit {
|
|
43
|
-
/**
|
|
44
|
-
* @return {LH.Audit.Meta}
|
|
45
|
-
*/
|
|
46
|
-
static get meta() {
|
|
47
|
-
return {
|
|
48
|
-
id: 'offscreen-images',
|
|
49
|
-
title: str_(UIStrings.title),
|
|
50
|
-
description: str_(UIStrings.description),
|
|
51
|
-
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
|
|
52
|
-
supportedModes: ['navigation'],
|
|
53
|
-
guidanceLevel: 2,
|
|
54
|
-
requiredArtifacts: ['ImageElements', 'ViewportDimensions', 'GatherContext', 'DevtoolsLog',
|
|
55
|
-
'Trace', 'URL', 'SourceMaps'],
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @param {{top: number, bottom: number, left: number, right: number}} imageRect
|
|
61
|
-
* @param {{innerWidth: number, innerHeight: number}} viewportDimensions
|
|
62
|
-
* @return {number}
|
|
63
|
-
*/
|
|
64
|
-
static computeVisiblePixels(imageRect, viewportDimensions) {
|
|
65
|
-
const innerWidth = viewportDimensions.innerWidth;
|
|
66
|
-
const innerHeight = viewportDimensions.innerHeight;
|
|
67
|
-
const allowableOffscreenBottomInPx = ALLOWABLE_OFFSCREEN_BOTTOM_IN_VIEWPORTS *
|
|
68
|
-
viewportDimensions.innerHeight;
|
|
69
|
-
|
|
70
|
-
const top = Math.max(imageRect.top, -1 * ALLOWABLE_OFFSCREEN_IN_PX);
|
|
71
|
-
const right = Math.min(imageRect.right, innerWidth + ALLOWABLE_OFFSCREEN_IN_PX);
|
|
72
|
-
const bottom = Math.min(imageRect.bottom, innerHeight + allowableOffscreenBottomInPx);
|
|
73
|
-
const left = Math.max(imageRect.left, -1 * ALLOWABLE_OFFSCREEN_IN_PX);
|
|
74
|
-
|
|
75
|
-
return Math.max(right - left, 0) * Math.max(bottom - top, 0);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @param {LH.Artifacts.ImageElement} image
|
|
80
|
-
* @param {{innerWidth: number, innerHeight: number}} viewportDimensions
|
|
81
|
-
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
82
|
-
* @return {null|Error|WasteResult}
|
|
83
|
-
*/
|
|
84
|
-
static computeWaste(image, viewportDimensions, networkRecords) {
|
|
85
|
-
const networkRecord = networkRecords.find(record => record.url === image.src);
|
|
86
|
-
// If we don't know how big it was, we can't really report savings, treat it as passed.
|
|
87
|
-
if (!networkRecord) return null;
|
|
88
|
-
// If the image had its loading behavior explicitly controlled already, treat it as passed.
|
|
89
|
-
if (image.loading === 'lazy' || image.loading === 'eager') return null;
|
|
90
|
-
|
|
91
|
-
const url = UrlUtils.elideDataURI(image.src);
|
|
92
|
-
const totalPixels = image.displayedWidth * image.displayedHeight;
|
|
93
|
-
const visiblePixels = this.computeVisiblePixels(image.clientRect, viewportDimensions);
|
|
94
|
-
// Treat images with 0 area as if they're offscreen. See https://github.com/GoogleChrome/lighthouse/issues/1914
|
|
95
|
-
const wastedRatio = totalPixels === 0 ? 1 : 1 - visiblePixels / totalPixels;
|
|
96
|
-
const totalBytes = NetworkRequest.getResourceSizeOnNetwork(networkRecord);
|
|
97
|
-
const wastedBytes = Math.round(totalBytes * wastedRatio);
|
|
98
|
-
|
|
99
|
-
if (!Number.isFinite(wastedRatio)) {
|
|
100
|
-
return new Error(`Invalid image sizing information ${url}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
node: ByteEfficiencyAudit.makeNodeItem(image.node),
|
|
105
|
-
url,
|
|
106
|
-
requestStartTime: networkRecord.networkRequestTime,
|
|
107
|
-
totalBytes,
|
|
108
|
-
wastedBytes,
|
|
109
|
-
wastedPercent: 100 * wastedRatio,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Filters out image requests that were requested after the last long task based on lantern timings.
|
|
115
|
-
*
|
|
116
|
-
* @param {WasteResult[]} images
|
|
117
|
-
* @param {LH.Artifacts.LanternMetric} lanternMetricData
|
|
118
|
-
*/
|
|
119
|
-
static filterLanternResults(images, lanternMetricData) {
|
|
120
|
-
const nodeTimings = lanternMetricData.pessimisticEstimate.nodeTimings;
|
|
121
|
-
|
|
122
|
-
// Find the last long task start time
|
|
123
|
-
let lastLongTaskStartTime = 0;
|
|
124
|
-
// Find the start time of all requests
|
|
125
|
-
/** @type {Map<string, number>} */
|
|
126
|
-
const startTimesByURL = new Map();
|
|
127
|
-
for (const [node, timing] of nodeTimings) {
|
|
128
|
-
if (node.type === 'cpu' && timing.duration >= 50) {
|
|
129
|
-
lastLongTaskStartTime = Math.max(lastLongTaskStartTime, timing.startTime);
|
|
130
|
-
} else if (node.type === 'network') {
|
|
131
|
-
startTimesByURL.set(node.request.url, timing.startTime);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return images.filter(image => {
|
|
136
|
-
// Filter out images that had little waste
|
|
137
|
-
if (image.wastedBytes < IGNORE_THRESHOLD_IN_BYTES) return false;
|
|
138
|
-
if (image.wastedPercent < IGNORE_THRESHOLD_IN_PERCENT) return false;
|
|
139
|
-
// Filter out images that started after the last long task
|
|
140
|
-
const imageRequestStartTime = startTimesByURL.get(image.url) || 0;
|
|
141
|
-
return imageRequestStartTime < lastLongTaskStartTime - IGNORE_THRESHOLD_IN_MS;
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Filters out image requests that were requested after TTI.
|
|
147
|
-
*
|
|
148
|
-
* @param {WasteResult[]} images
|
|
149
|
-
* @param {number} interactiveTimestamp
|
|
150
|
-
*/
|
|
151
|
-
static filterObservedResults(images, interactiveTimestamp) {
|
|
152
|
-
return images.filter(image => {
|
|
153
|
-
if (image.wastedBytes < IGNORE_THRESHOLD_IN_BYTES) return false;
|
|
154
|
-
if (image.wastedPercent < IGNORE_THRESHOLD_IN_PERCENT) return false;
|
|
155
|
-
return image.requestStartTime < interactiveTimestamp / 1000 - IGNORE_THRESHOLD_IN_MS;
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @param {LH.Artifacts} artifacts
|
|
161
|
-
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
|
162
|
-
* @param {LH.Audit.Context} context
|
|
163
|
-
* @return {Promise<import('./byte-efficiency-audit.js').ByteEfficiencyProduct>}
|
|
164
|
-
*/
|
|
165
|
-
static async audit_(artifacts, networkRecords, context) {
|
|
166
|
-
const {URL, SourceMaps} = artifacts;
|
|
167
|
-
const images = artifacts.ImageElements;
|
|
168
|
-
const viewportDimensions = artifacts.ViewportDimensions;
|
|
169
|
-
const gatherContext = artifacts.GatherContext;
|
|
170
|
-
const trace = artifacts.Trace;
|
|
171
|
-
const devtoolsLog = artifacts.DevtoolsLog;
|
|
172
|
-
|
|
173
|
-
/** @type {string[]} */
|
|
174
|
-
const warnings = [];
|
|
175
|
-
/** @type {Map<string, WasteResult>} */
|
|
176
|
-
const resultsMap = new Map();
|
|
177
|
-
for (const image of images) {
|
|
178
|
-
const processed = OffscreenImages.computeWaste(image, viewportDimensions, networkRecords);
|
|
179
|
-
if (processed === null) {
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (processed instanceof Error) {
|
|
184
|
-
warnings.push(processed.message);
|
|
185
|
-
Sentry.captureException(processed, {tags: {audit: this.meta.id}, level: 'warning'});
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// If an image was used more than once, warn only about its least wasteful usage
|
|
190
|
-
const existing = resultsMap.get(processed.url);
|
|
191
|
-
if (!existing || existing.wastedBytes > processed.wastedBytes) {
|
|
192
|
-
resultsMap.set(processed.url, processed);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const settings = context.settings;
|
|
197
|
-
|
|
198
|
-
let items;
|
|
199
|
-
const unfilteredResults = Array.from(resultsMap.values());
|
|
200
|
-
// get the interactive time or fallback to getting the end of trace time
|
|
201
|
-
try {
|
|
202
|
-
const metricComputationData =
|
|
203
|
-
{trace, devtoolsLog, gatherContext, settings, URL, SourceMaps, simulator: null};
|
|
204
|
-
const interactive = await Interactive.request(metricComputationData, context);
|
|
205
|
-
|
|
206
|
-
// use interactive to generate items
|
|
207
|
-
const lanternInteractive = /** @type {LH.Artifacts.LanternMetric} */ (interactive);
|
|
208
|
-
// Filter out images that were loaded after all CPU activity
|
|
209
|
-
items = context.settings.throttlingMethod === 'simulate' ?
|
|
210
|
-
OffscreenImages.filterLanternResults(unfilteredResults, lanternInteractive) :
|
|
211
|
-
// @ts-expect-error - .timestamp will exist if throttlingMethod isn't lantern
|
|
212
|
-
OffscreenImages.filterObservedResults(unfilteredResults, interactive.timestamp);
|
|
213
|
-
} catch (err) {
|
|
214
|
-
// if the error is during a Lantern run, end of trace may also be inaccurate, so rethrow
|
|
215
|
-
if (context.settings.throttlingMethod === 'simulate') {
|
|
216
|
-
throw err;
|
|
217
|
-
}
|
|
218
|
-
// use end of trace as a substitute for finding interactive time
|
|
219
|
-
items = OffscreenImages.filterObservedResults(unfilteredResults,
|
|
220
|
-
await ProcessedTrace.request(trace, context).then(tot => tot.timestamps.traceEnd));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
224
|
-
const headings = [
|
|
225
|
-
{key: 'node', valueType: 'node', label: ''},
|
|
226
|
-
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
227
|
-
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnResourceSize)},
|
|
228
|
-
{key: 'wastedBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnWastedBytes)},
|
|
229
|
-
];
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
warnings,
|
|
233
|
-
items,
|
|
234
|
-
headings,
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export default OffscreenImages;
|
|
240
|
-
export {UIStrings};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
export default RenderBlockingResources;
|
|
2
|
-
declare class RenderBlockingResources extends Audit {
|
|
3
|
-
/**
|
|
4
|
-
* @param {LH.Artifacts} artifacts
|
|
5
|
-
* @param {LH.Audit.Context} context
|
|
6
|
-
* @return {Promise<{fcpWastedMs: number, lcpWastedMs: number, results: Array<{url: string, totalBytes: number, wastedMs: number}>}>}
|
|
7
|
-
*/
|
|
8
|
-
static computeResults(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<{
|
|
9
|
-
fcpWastedMs: number;
|
|
10
|
-
lcpWastedMs: number;
|
|
11
|
-
results: Array<{
|
|
12
|
-
url: string;
|
|
13
|
-
totalBytes: number;
|
|
14
|
-
wastedMs: number;
|
|
15
|
-
}>;
|
|
16
|
-
}>;
|
|
17
|
-
/**
|
|
18
|
-
* Estimates how much faster this page would reach FCP if we inlined all the used CSS from the
|
|
19
|
-
* render blocking stylesheets and deferred all the scripts. This is more conservative than
|
|
20
|
-
* removing all the assets and more aggressive than inlining everything.
|
|
21
|
-
*
|
|
22
|
-
* *Most* of the time, scripts in the head are there accidentally/due to lack of awareness
|
|
23
|
-
* rather than necessity, so we're comfortable with this balance. In the worst case, we're telling
|
|
24
|
-
* devs that they should be able to get to a reasonable first paint without JS, which is not a bad
|
|
25
|
-
* thing.
|
|
26
|
-
*
|
|
27
|
-
* @param {LH.Gatherer.Simulation.Simulator} simulator
|
|
28
|
-
* @param {LH.Gatherer.Simulation.GraphNode} fcpGraph
|
|
29
|
-
* @param {Set<string>} deferredIds
|
|
30
|
-
* @param {Map<string, number>} wastedCssBytesByUrl
|
|
31
|
-
* @param {LH.Artifacts.DetectedStack[]} Stacks
|
|
32
|
-
* @return {number}
|
|
33
|
-
*/
|
|
34
|
-
static estimateSavingsWithGraphs(simulator: LH.Gatherer.Simulation.Simulator, fcpGraph: LH.Gatherer.Simulation.GraphNode, deferredIds: Set<string>, wastedCssBytesByUrl: Map<string, number>, Stacks: LH.Artifacts.DetectedStack[]): number;
|
|
35
|
-
/**
|
|
36
|
-
* @param {LH.Artifacts} artifacts
|
|
37
|
-
* @param {LH.Audit.Context} context
|
|
38
|
-
* @return {Promise<Map<string, number>>}
|
|
39
|
-
*/
|
|
40
|
-
static computeWastedCSSBytes(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<Map<string, number>>;
|
|
41
|
-
/**
|
|
42
|
-
* @param {LH.Artifacts} artifacts
|
|
43
|
-
* @param {LH.Audit.Context} context
|
|
44
|
-
* @return {Promise<LH.Audit.Product>}
|
|
45
|
-
*/
|
|
46
|
-
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
47
|
-
}
|
|
48
|
-
export namespace UIStrings {
|
|
49
|
-
let title: string;
|
|
50
|
-
let description: string;
|
|
51
|
-
}
|
|
52
|
-
import { Audit } from '../audit.js';
|
|
53
|
-
//# sourceMappingURL=render-blocking-resources.d.ts.map
|