core(image-elements): remove resourceSize property (#11733)
This commit is contained in:
Родитель
2fa473fe8d
Коммит
c051eebe4f
|
@ -80,7 +80,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|||
static computeWaste(image, viewportDimensions, networkRecords) {
|
||||
const networkRecord = networkRecords.find(record => record.url === image.src);
|
||||
// If we don't know how big it was, we can't really report savings, treat it as passed.
|
||||
if (!image.resourceSize || !networkRecord) return null;
|
||||
if (!networkRecord) return null;
|
||||
// If the image had its loading behavior explicitly controlled already, treat it as passed.
|
||||
if (image.loading === 'lazy' || image.loading === 'eager') return null;
|
||||
|
||||
|
@ -89,7 +89,13 @@ class OffscreenImages extends ByteEfficiencyAudit {
|
|||
const visiblePixels = this.computeVisiblePixels(image.clientRect, viewportDimensions);
|
||||
// Treat images with 0 area as if they're offscreen. See https://github.com/GoogleChrome/lighthouse/issues/1914
|
||||
const wastedRatio = totalPixels === 0 ? 1 : 1 - visiblePixels / totalPixels;
|
||||
const totalBytes = image.resourceSize;
|
||||
// Resource size is almost always the right one to be using because of the below:
|
||||
// transferSize = resourceSize + headers.length
|
||||
// HOWEVER, there are some cases where an image is compressed again over the network and transfer size
|
||||
// is smaller (see https://github.com/GoogleChrome/lighthouse/pull/4968).
|
||||
// Use the min of the two numbers to be safe.
|
||||
const {resourceSize = 0, transferSize = 0} = networkRecord;
|
||||
const totalBytes = Math.min(resourceSize, transferSize);
|
||||
const wastedBytes = Math.round(totalBytes * wastedRatio);
|
||||
|
||||
if (!Number.isFinite(wastedRatio)) {
|
||||
|
|
|
@ -49,11 +49,13 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|||
/**
|
||||
* @param {LH.Artifacts.ImageElement} image
|
||||
* @param {LH.Artifacts.ViewportDimensions} ViewportDimensions
|
||||
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
||||
* @return {null|Error|LH.Audit.ByteEfficiencyItem};
|
||||
*/
|
||||
static computeWaste(image, ViewportDimensions) {
|
||||
// Nothing can be done without network info.
|
||||
if (!image.resourceSize) {
|
||||
static computeWaste(image, ViewportDimensions, networkRecords) {
|
||||
const networkRecord = networkRecords.find(record => record.url === image.src);
|
||||
// Nothing can be done without network info, ignore images without resource size information.
|
||||
if (!networkRecord) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -81,7 +83,13 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|||
const url = URL.elideDataURI(image.src);
|
||||
const actualPixels = image.naturalWidth * image.naturalHeight;
|
||||
const wastedRatio = 1 - (usedPixels / actualPixels);
|
||||
const totalBytes = image.resourceSize;
|
||||
// Resource size is almost always the right one to be using because of the below:
|
||||
// transferSize = resourceSize + headers.length
|
||||
// HOWEVER, there are some cases where an image is compressed again over the network and transfer size
|
||||
// is smaller (see https://github.com/GoogleChrome/lighthouse/pull/4968).
|
||||
// Use the min of the two numbers to be safe.
|
||||
const {resourceSize = 0, transferSize = 0} = networkRecord;
|
||||
const totalBytes = Math.min(resourceSize, transferSize);
|
||||
const wastedBytes = Math.round(totalBytes * wastedRatio);
|
||||
|
||||
if (!Number.isFinite(wastedRatio)) {
|
||||
|
@ -98,9 +106,10 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|||
|
||||
/**
|
||||
* @param {LH.Artifacts} artifacts
|
||||
* @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
|
||||
* @return {ByteEfficiencyAudit.ByteEfficiencyProduct}
|
||||
*/
|
||||
static audit_(artifacts) {
|
||||
static audit_(artifacts, networkRecords) {
|
||||
const images = artifacts.ImageElements;
|
||||
const ViewportDimensions = artifacts.ViewportDimensions;
|
||||
|
||||
|
@ -109,15 +118,15 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
|
|||
/** @type {Map<string, LH.Audit.ByteEfficiencyItem>} */
|
||||
const resultsMap = new Map();
|
||||
for (const image of images) {
|
||||
// Ignore images without resource size information.
|
||||
// Give SVG a free pass because creating a "responsive" SVG is of questionable value.
|
||||
// Ignore CSS images because it's difficult to determine what is a spritesheet,
|
||||
// and the reward-to-effort ratio for responsive CSS images is quite low https://css-tricks.com/responsive-images-css/.
|
||||
if (!image.resourceSize || image.mimeType === 'image/svg+xml' || image.isCss) {
|
||||
if (image.mimeType === 'image/svg+xml' || image.isCss) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const processed = UsesResponsiveImages.computeWaste(image, ViewportDimensions);
|
||||
/* eslint-disable max-len */
|
||||
const processed = UsesResponsiveImages.computeWaste(image, ViewportDimensions, networkRecords);
|
||||
if (!processed) continue;
|
||||
|
||||
if (processed instanceof Error) {
|
||||
|
|
|
@ -16,7 +16,6 @@ const FontSize = require('./seo/font-size.js');
|
|||
|
||||
/* global window, getElementsInDocument, Image, getNodeDetails, ShadowRoot */
|
||||
|
||||
|
||||
/** @param {Element} element */
|
||||
/* istanbul ignore next */
|
||||
function getClientRect(element) {
|
||||
|
@ -77,7 +76,6 @@ function getHTMLImages(allElements) {
|
|||
isCss: false,
|
||||
isPicture,
|
||||
loading: element.loading,
|
||||
resourceSize: 0, // this will get overwritten below
|
||||
usesObjectFit: ['cover', 'contain', 'scale-down', 'none'].includes(
|
||||
computedStyle.getPropertyValue('object-fit')
|
||||
),
|
||||
|
@ -137,7 +135,6 @@ function getCSSImages(allElements) {
|
|||
style.getPropertyValue('image-rendering')
|
||||
),
|
||||
usesSrcSetDensityDescriptor: false,
|
||||
resourceSize: 0, // this will get overwritten below
|
||||
// @ts-expect-error - getNodeDetails put into scope via stringification
|
||||
...getNodeDetails(element),
|
||||
});
|
||||
|
@ -332,13 +329,6 @@ class ImageElements extends Gatherer {
|
|||
// Pull some of our information directly off the network record.
|
||||
const networkRecord = indexedNetworkRecords[element.src] || {};
|
||||
element.mimeType = networkRecord.mimeType;
|
||||
// Resource size is almost always the right one to be using because of the below:
|
||||
// transferSize = resourceSize + headers.length
|
||||
// HOWEVER, there are some cases where an image is compressed again over the network and transfer size
|
||||
// is smaller (see https://github.com/GoogleChrome/lighthouse/pull/4968).
|
||||
// Use the min of the two numbers to be safe.
|
||||
const {resourceSize = 0, transferSize = 0} = networkRecord;
|
||||
element.resourceSize = Math.min(resourceSize, transferSize);
|
||||
|
||||
if (!element.isInShadowDOM && !element.isCss) {
|
||||
await this.fetchSourceRules(driver, element.devtoolsNodePath, element);
|
||||
|
|
|
@ -23,6 +23,7 @@ function generateRecord({
|
|||
mimeType,
|
||||
startTime, // DevTools timestamp which is in seconds.
|
||||
resourceSize: resourceSizeInKb * 1024,
|
||||
transferSize: resourceSizeInKb * 1024,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -408,6 +409,7 @@ describe('OffscreenImages audit', () => {
|
|||
const recordA = {
|
||||
url: 'https://example.com/a',
|
||||
resourceSize: wastedSize,
|
||||
transferSize: wastedSize,
|
||||
requestId: 'a',
|
||||
startTime: 1,
|
||||
priority: 'High',
|
||||
|
@ -416,6 +418,7 @@ describe('OffscreenImages audit', () => {
|
|||
const recordB = {
|
||||
url: 'https://example.com/b',
|
||||
resourceSize: wastedSize,
|
||||
transferSize: wastedSize,
|
||||
requestId: 'b',
|
||||
startTime: 2.25,
|
||||
priority: 'High',
|
||||
|
@ -461,6 +464,7 @@ describe('OffscreenImages audit', () => {
|
|||
const recordA = {
|
||||
url: 'https://example.com/a',
|
||||
resourceSize: wastedSize,
|
||||
transferSize: wastedSize,
|
||||
requestId: 'a',
|
||||
startTime: 1,
|
||||
priority: 'High',
|
||||
|
@ -469,6 +473,7 @@ describe('OffscreenImages audit', () => {
|
|||
const recordB = {
|
||||
url: 'https://example.com/b',
|
||||
resourceSize: wastedSize,
|
||||
transferSize: wastedSize,
|
||||
requestId: 'b',
|
||||
startTime: 1.25,
|
||||
priority: 'High',
|
||||
|
|
|
@ -10,12 +10,14 @@ const UsesResponsiveImagesAudit =
|
|||
const assert = require('assert').strict;
|
||||
|
||||
/* eslint-env jest */
|
||||
function generateRecord(resourceSizeInKb, durationInMs, mimeType = 'image/png') {
|
||||
function generateRecord(resourceSizeInKb, durationInMs, url = 'https://google.com/logo.png', mimeType = 'image/png') {
|
||||
return {
|
||||
mimeType,
|
||||
resourceSize: resourceSizeInKb * 1024,
|
||||
transferSize: resourceSizeInKb * 1024,
|
||||
endTime: durationInMs / 1000,
|
||||
responseReceivedTime: 0,
|
||||
url,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -26,32 +28,29 @@ function generateSize(width, height, prefix = 'displayed') {
|
|||
return size;
|
||||
}
|
||||
|
||||
function generateImage(clientSize, naturalSize, networkRecord, src = 'https://google.com/logo.png') {
|
||||
Object.assign(networkRecord || {}, {url: src});
|
||||
const image = {src, ...networkRecord};
|
||||
Object.assign(image, clientSize, naturalSize);
|
||||
return image;
|
||||
function generateImage(clientSize, naturalSize, src = 'https://google.com/logo.png') {
|
||||
return {src, ...clientSize, ...naturalSize};
|
||||
}
|
||||
|
||||
describe('Page uses responsive images', () => {
|
||||
function testImage(condition, data) {
|
||||
const description = `identifies when an image is ${condition}`;
|
||||
const artifacts = {
|
||||
ViewportDimensions: {
|
||||
innerWidth: 1000,
|
||||
innerHeight: 1000,
|
||||
devicePixelRatio: data.devicePixelRatio || 1,
|
||||
},
|
||||
ImageElements: [
|
||||
generateImage(
|
||||
generateSize(...data.clientSize),
|
||||
generateSize(...data.naturalSize, 'natural')
|
||||
),
|
||||
],
|
||||
};
|
||||
it(description, () => {
|
||||
const result = UsesResponsiveImagesAudit.audit_({
|
||||
ViewportDimensions: {
|
||||
innerWidth: 1000,
|
||||
innerHeight: 1000,
|
||||
devicePixelRatio: data.devicePixelRatio || 1,
|
||||
},
|
||||
ImageElements: [
|
||||
generateImage(
|
||||
generateSize(...data.clientSize),
|
||||
generateSize(...data.naturalSize, 'natural'),
|
||||
generateRecord(data.sizeInKb, data.durationInMs || 200)
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
const result = UsesResponsiveImagesAudit.audit_(artifacts, [generateRecord(data.sizeInKb, data.durationInMs || 200)]);
|
||||
assert.equal(result.items.length, data.listed ? 1 : 0);
|
||||
if (data.listed) {
|
||||
assert.equal(Math.round(result.items[0].wastedBytes / 1024), data.expectedWaste);
|
||||
|
@ -120,35 +119,37 @@ describe('Page uses responsive images', () => {
|
|||
null
|
||||
),
|
||||
],
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
assert.equal(auditResult.items.length, 0);
|
||||
});
|
||||
|
||||
it('identifies when images are not wasteful', () => {
|
||||
const networkRecords = [generateRecord(100, 300, 'https://google.com/logo.png'), generateRecord(90, 500, 'https://google.com/logo2.png'), generateRecord(20, 100, 'data:image/jpeg;base64,foobar')];
|
||||
const auditResult = UsesResponsiveImagesAudit.audit_({
|
||||
ViewportDimensions: {innerWidth: 1000, innerHeight: 1000, devicePixelRatio: 2},
|
||||
ImageElements: [
|
||||
generateImage(
|
||||
generateSize(200, 200),
|
||||
generateSize(450, 450, 'natural'),
|
||||
generateRecord(100, 300),
|
||||
'https://google.com/logo.png'
|
||||
),
|
||||
generateImage(
|
||||
generateSize(100, 100),
|
||||
generateSize(210, 210, 'natural'),
|
||||
generateRecord(90, 500),
|
||||
'https://google.com/logo2.png'
|
||||
),
|
||||
generateImage(
|
||||
generateSize(100, 100),
|
||||
generateSize(80, 80, 'natural'),
|
||||
generateRecord(20, 100),
|
||||
'data:image/jpeg;base64,foobar'
|
||||
),
|
||||
],
|
||||
});
|
||||
},
|
||||
networkRecords
|
||||
);
|
||||
|
||||
assert.equal(auditResult.items.length, 2);
|
||||
});
|
||||
|
@ -156,29 +157,31 @@ describe('Page uses responsive images', () => {
|
|||
it('ignores vectors', () => {
|
||||
const urlA = 'https://google.com/logo.svg';
|
||||
const naturalSizeA = generateSize(450, 450, 'natural');
|
||||
const recordA = generateRecord(100, 300, 'image/svg+xml');
|
||||
|
||||
const image =
|
||||
{...generateImage(generateSize(10, 10), naturalSizeA, urlA), mimeType: 'image/svg+xml'};
|
||||
const auditResult = UsesResponsiveImagesAudit.audit_({
|
||||
ViewportDimensions: {innerWidth: 1000, innerHeight: 1000, devicePixelRatio: 1},
|
||||
ImageElements: [
|
||||
generateImage(generateSize(10, 10), naturalSizeA, recordA, urlA),
|
||||
image,
|
||||
],
|
||||
});
|
||||
|
||||
},
|
||||
[generateRecord(100, 300, urlA, 'image/svg+xml')]
|
||||
);
|
||||
assert.equal(auditResult.items.length, 0);
|
||||
});
|
||||
|
||||
it('ignores CSS', () => {
|
||||
const urlA = 'https://google.com/logo.png';
|
||||
const naturalSizeA = generateSize(450, 450, 'natural');
|
||||
const recordA = generateRecord(100, 300);
|
||||
|
||||
const auditResult = UsesResponsiveImagesAudit.audit_({
|
||||
ViewportDimensions: {innerWidth: 1000, innerHeight: 1000, devicePixelRatio: 1},
|
||||
ImageElements: [
|
||||
{...generateImage(generateSize(10, 10), naturalSizeA, recordA, urlA), isCss: true},
|
||||
{...generateImage(generateSize(10, 10), naturalSizeA, urlA), isCss: true},
|
||||
],
|
||||
});
|
||||
},
|
||||
[generateRecord(100, 300, urlA)]
|
||||
);
|
||||
|
||||
assert.equal(auditResult.items.length, 0);
|
||||
});
|
||||
|
@ -186,14 +189,14 @@ describe('Page uses responsive images', () => {
|
|||
it('handles failure', () => {
|
||||
const urlA = 'https://google.com/logo.png';
|
||||
const naturalSizeA = generateSize(NaN, 450, 'natural');
|
||||
const recordA = generateRecord(100, 300);
|
||||
|
||||
const auditResult = UsesResponsiveImagesAudit.audit_({
|
||||
ViewportDimensions: {innerWidth: 1000, innerHeight: 1000, devicePixelRatio: 1},
|
||||
ImageElements: [
|
||||
generateImage(generateSize(10, 10), naturalSizeA, recordA, urlA),
|
||||
generateImage(generateSize(10, 10), naturalSizeA, urlA),
|
||||
],
|
||||
});
|
||||
},
|
||||
[generateRecord(100, 300, urlA)]
|
||||
);
|
||||
|
||||
assert.equal(auditResult.items.length, 0);
|
||||
assert.equal(auditResult.warnings.length, 1);
|
||||
|
@ -202,21 +205,24 @@ describe('Page uses responsive images', () => {
|
|||
it('de-dupes images', () => {
|
||||
const urlA = 'https://google.com/logo.png';
|
||||
const naturalSizeA = generateSize(450, 450, 'natural');
|
||||
const recordA = generateRecord(100, 300);
|
||||
const recordA = generateRecord(100, 300, urlA);
|
||||
const urlB = 'https://google.com/logoB.png';
|
||||
const naturalSizeB = generateSize(1000, 1000, 'natural');
|
||||
const recordB = generateRecord(10, 20); // make it small to still test passing
|
||||
const recordB = generateRecord(10, 20, urlB); // make it small to keep test passing
|
||||
const networkRecords = [recordA, recordB];
|
||||
|
||||
const auditResult = UsesResponsiveImagesAudit.audit_({
|
||||
ViewportDimensions: {innerWidth: 1000, innerHeight: 1000, devicePixelRatio: 1},
|
||||
ImageElements: [
|
||||
generateImage(generateSize(10, 10), naturalSizeA, recordA, urlA),
|
||||
generateImage(generateSize(450, 450), naturalSizeA, recordA, urlA),
|
||||
generateImage(generateSize(30, 30), naturalSizeA, recordA, urlA),
|
||||
generateImage(generateSize(500, 500), naturalSizeB, recordB, urlB),
|
||||
generateImage(generateSize(100, 100), naturalSizeB, recordB, urlB),
|
||||
generateImage(generateSize(10, 10), naturalSizeA, urlA),
|
||||
generateImage(generateSize(450, 450), naturalSizeA, urlA),
|
||||
generateImage(generateSize(30, 30), naturalSizeA, urlA),
|
||||
generateImage(generateSize(500, 500), naturalSizeB, urlB),
|
||||
generateImage(generateSize(100, 100), naturalSizeB, urlB),
|
||||
],
|
||||
});
|
||||
},
|
||||
networkRecords
|
||||
);
|
||||
|
||||
assert.equal(auditResult.items.length, 1);
|
||||
assert.equal(auditResult.items[0].wastedPercent, 75, 'correctly computes wastedPercent');
|
||||
|
|
|
@ -1224,70 +1224,358 @@
|
|||
],
|
||||
"ImageElements": [
|
||||
{
|
||||
"src": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg",
|
||||
"displayedWidth": 480,
|
||||
"displayedHeight": 57,
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?iar1",
|
||||
"srcset": "",
|
||||
"displayedWidth": 120,
|
||||
"displayedHeight": 15,
|
||||
"clientRect": {
|
||||
"top": 103.8125,
|
||||
"bottom": 160.8125,
|
||||
"top": 638.8125,
|
||||
"bottom": 653.8125,
|
||||
"left": 8,
|
||||
"right": 488
|
||||
"right": 128
|
||||
},
|
||||
"naturalWidth": 480,
|
||||
"naturalHeight": 318,
|
||||
"attributeWidth": 480,
|
||||
"attributeHeight": 318,
|
||||
"attributeWidth": "120",
|
||||
"attributeHeight": "15",
|
||||
"cssComputedPosition": "static",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"isInShadowDOM": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"resourceSize": 24620,
|
||||
"mimeType": "image/jpeg"
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-0-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,12,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 639,
|
||||
"bottom": 654,
|
||||
"left": 8,
|
||||
"right": 128,
|
||||
"width": 120,
|
||||
"height": 15
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-480x318.jpg?iar1\" width=\"120\" height=\"15\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/jpeg",
|
||||
"cssWidth": "120px",
|
||||
"cssHeight": "15px"
|
||||
},
|
||||
{
|
||||
"src": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg",
|
||||
"displayedWidth": 480,
|
||||
"displayedHeight": 318,
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?iar2",
|
||||
"srcset": "",
|
||||
"displayedWidth": 120,
|
||||
"displayedHeight": 80,
|
||||
"clientRect": {
|
||||
"top": 164.8125,
|
||||
"bottom": 482.8125,
|
||||
"left": 8,
|
||||
"right": 488
|
||||
"top": 573.8125,
|
||||
"bottom": 653.8125,
|
||||
"left": 132,
|
||||
"right": 252
|
||||
},
|
||||
"naturalWidth": 480,
|
||||
"naturalHeight": 318,
|
||||
"attributeWidth": "",
|
||||
"attributeHeight": "",
|
||||
"cssWidth": "auto",
|
||||
"cssHeight": "auto",
|
||||
"attributeWidth": "120",
|
||||
"attributeHeight": "80",
|
||||
"cssComputedPosition": "static",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"isInShadowDOM": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"resourceSize": 24620,
|
||||
"mimeType": "image/jpeg"
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-1-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,14,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 574,
|
||||
"bottom": 654,
|
||||
"left": 132,
|
||||
"right": 252,
|
||||
"width": 120,
|
||||
"height": 80
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-480x318.jpg?iar2\" width=\"120\" height=\"80\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/jpeg",
|
||||
"cssWidth": "120px",
|
||||
"cssHeight": "80px"
|
||||
},
|
||||
{
|
||||
"src": "blob:http://localhost:10200/ae0eac03-ab9b-4a6a-b299-f5212153e277",
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?isr1",
|
||||
"srcset": "",
|
||||
"displayedWidth": 4800,
|
||||
"displayedHeight": 3180,
|
||||
"clientRect": {
|
||||
"top": 573.8125,
|
||||
"bottom": 3753.8125,
|
||||
"left": 252,
|
||||
"right": 5052
|
||||
},
|
||||
"naturalWidth": 480,
|
||||
"naturalHeight": 318,
|
||||
"attributeWidth": "4800",
|
||||
"attributeHeight": "3180",
|
||||
"cssComputedPosition": "absolute",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-2-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,16,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 574,
|
||||
"bottom": 3754,
|
||||
"left": 252,
|
||||
"right": 5052,
|
||||
"width": 4800,
|
||||
"height": 3180
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-480x318.jpg?isr1\" width=\"4800\" height=\"3180\" style=\"position: absolute;\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/jpeg",
|
||||
"cssWidth": "4800px",
|
||||
"cssHeight": "3180px"
|
||||
},
|
||||
{
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?isr2",
|
||||
"srcset": "",
|
||||
"displayedWidth": 120,
|
||||
"displayedHeight": 80,
|
||||
"clientRect": {
|
||||
"top": 573.8125,
|
||||
"bottom": 653.8125,
|
||||
"left": 252,
|
||||
"right": 372
|
||||
},
|
||||
"naturalWidth": 480,
|
||||
"naturalHeight": 318,
|
||||
"attributeWidth": "120",
|
||||
"attributeHeight": "80",
|
||||
"cssComputedPosition": "absolute",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-3-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,18,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 574,
|
||||
"bottom": 654,
|
||||
"left": 252,
|
||||
"right": 372,
|
||||
"width": 120,
|
||||
"height": 80
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-480x318.jpg?isr2\" width=\"120\" height=\"80\" style=\"position: absolute;\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/jpeg",
|
||||
"cssWidth": "120px",
|
||||
"cssHeight": "80px"
|
||||
},
|
||||
{
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?isr3",
|
||||
"srcset": "",
|
||||
"displayedWidth": 960,
|
||||
"displayedHeight": 636,
|
||||
"clientRect": {
|
||||
"top": 573.8125,
|
||||
"bottom": 1209.8125,
|
||||
"left": 252,
|
||||
"right": 1212
|
||||
},
|
||||
"naturalWidth": 480,
|
||||
"naturalHeight": 318,
|
||||
"attributeWidth": "960",
|
||||
"attributeHeight": "636",
|
||||
"cssComputedPosition": "absolute",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": true,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-4-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,20,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 574,
|
||||
"bottom": 1210,
|
||||
"left": 252,
|
||||
"right": 1212,
|
||||
"width": 960,
|
||||
"height": 636
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-480x318.jpg?isr3\" width=\"960\" height=\"636\" style=\"image-rendering: pixelated; position: absolute;\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/jpeg",
|
||||
"cssWidth": "960px",
|
||||
"cssHeight": "636px"
|
||||
},
|
||||
{
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg",
|
||||
"srcset": "lighthouse-480x318.jpg 2x",
|
||||
"displayedWidth": 960,
|
||||
"displayedHeight": 636,
|
||||
"clientRect": {
|
||||
"top": 573.8125,
|
||||
"bottom": 1209.8125,
|
||||
"left": 252,
|
||||
"right": 1212
|
||||
},
|
||||
"naturalWidth": 480,
|
||||
"naturalHeight": 318,
|
||||
"attributeWidth": "960",
|
||||
"attributeHeight": "636",
|
||||
"cssComputedPosition": "absolute",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": true,
|
||||
"lhId": "page-5-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,22,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 574,
|
||||
"bottom": 1210,
|
||||
"left": 252,
|
||||
"right": 1212,
|
||||
"width": 960,
|
||||
"height": 636
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-480x318.jpg?isr4\" srcset=\"lighthouse-480x318.jpg 2x\" width=\"960\" height=\"636\" style=\"position: absolute;\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/jpeg",
|
||||
"cssWidth": "960px",
|
||||
"cssHeight": "636px"
|
||||
},
|
||||
{
|
||||
"src": "http://localhost:64707/dobetterweb/lighthouse-rotating.gif",
|
||||
"srcset": "",
|
||||
"displayedWidth": 811,
|
||||
"displayedHeight": 462,
|
||||
"clientRect": {
|
||||
"top": 657.8125,
|
||||
"bottom": 1119.8125,
|
||||
"left": 8,
|
||||
"right": 819
|
||||
},
|
||||
"naturalWidth": 811,
|
||||
"naturalHeight": 462,
|
||||
"attributeWidth": "811",
|
||||
"attributeHeight": "462",
|
||||
"cssComputedPosition": "static",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-6-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,24,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 658,
|
||||
"bottom": 1120,
|
||||
"left": 8,
|
||||
"right": 819,
|
||||
"width": 811,
|
||||
"height": 462
|
||||
},
|
||||
"snippet": "<img src=\"lighthouse-rotating.gif\" width=\"811\" height=\"462\">",
|
||||
"nodeLabel": "img",
|
||||
"mimeType": "image/gif",
|
||||
"cssWidth": "811px",
|
||||
"cssHeight": "462px"
|
||||
},
|
||||
{
|
||||
"src": "blob:http://localhost:64707/803723f3-114a-4dbd-ad67-c44f8174ef58",
|
||||
"srcset": "",
|
||||
"displayedWidth": 16,
|
||||
"displayedHeight": 16,
|
||||
"clientRect": {
|
||||
"top": 559.8125,
|
||||
"bottom": 575.8125,
|
||||
"left": 143,
|
||||
"right": 159
|
||||
"top": 1294.8125,
|
||||
"bottom": 1310.8125,
|
||||
"left": 322,
|
||||
"right": 338
|
||||
},
|
||||
"naturalWidth": 0,
|
||||
"naturalHeight": 0,
|
||||
"attributeWidth": "",
|
||||
"attributeHeight": "",
|
||||
"cssComputedPosition": "fixed",
|
||||
"cssComputedPosition": "static",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesObjectFit": false
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-7-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,63,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 1295,
|
||||
"bottom": 1311,
|
||||
"left": 322,
|
||||
"right": 338,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"snippet": "<img src=\"blob:http://localhost:64707/803723f3-114a-4dbd-ad67-c44f8174ef58\">",
|
||||
"nodeLabel": "img"
|
||||
},
|
||||
{
|
||||
"src": "filesystem:http://localhost:64707/temporary/empty-0.4587600445763731.png",
|
||||
"srcset": "",
|
||||
"displayedWidth": 16,
|
||||
"displayedHeight": 16,
|
||||
"clientRect": {
|
||||
"top": 1316.8125,
|
||||
"bottom": 1332.8125,
|
||||
"left": 8,
|
||||
"right": 24
|
||||
},
|
||||
"naturalWidth": 0,
|
||||
"naturalHeight": 0,
|
||||
"attributeWidth": "",
|
||||
"attributeHeight": "",
|
||||
"cssComputedPosition": "static",
|
||||
"isCss": false,
|
||||
"isPicture": false,
|
||||
"loading": "auto",
|
||||
"usesObjectFit": false,
|
||||
"usesPixelArtScaling": false,
|
||||
"isInShadowDOM": false,
|
||||
"usesSrcSetDensityDescriptor": false,
|
||||
"lhId": "page-8-IMG",
|
||||
"devtoolsNodePath": "3,HTML,1,BODY,72,IMG",
|
||||
"selector": "body > img",
|
||||
"boundingRect": {
|
||||
"top": 1317,
|
||||
"bottom": 1333,
|
||||
"left": 8,
|
||||
"right": 24,
|
||||
"width": 16,
|
||||
"height": 16
|
||||
},
|
||||
"snippet": "<img src=\"filesystem:http://localhost:64707/temporary/empty-0.4587600445763731.png\">",
|
||||
"nodeLabel": "img"
|
||||
}
|
||||
],
|
||||
"Accessibility": {
|
||||
|
|
|
@ -638,8 +638,8 @@
|
|||
],
|
||||
"items": [
|
||||
{
|
||||
"url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg",
|
||||
"displayedAspectRatio": "480 x 57\n (8.42)",
|
||||
"url": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?iar1",
|
||||
"displayedAspectRatio": "120 x 15\n (8.00)",
|
||||
"actualAspectRatio": "480 x 318\n (1.51)",
|
||||
"doRatiosMatch": false
|
||||
}
|
||||
|
@ -683,13 +683,22 @@
|
|||
],
|
||||
"items": [
|
||||
{
|
||||
"url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg",
|
||||
"elidedUrl": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg",
|
||||
"displayedSize": "480 x 318",
|
||||
"url": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?isr1",
|
||||
"elidedUrl": "http://localhost:64707/dobetterweb/lighthouse-480x318.jpg?isr1",
|
||||
"displayedSize": "4800 x 3180",
|
||||
"actualSize": "480 x 318",
|
||||
"actualPixels": 152640,
|
||||
"expectedSize": "960 x 636",
|
||||
"expectedPixels": 610560
|
||||
"expectedSize": "9600 x 6360",
|
||||
"expectedPixels": 61056000
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:64707/dobetterweb/lighthouse-rotating.gif",
|
||||
"elidedUrl": "http://localhost:64707/dobetterweb/lighthouse-rotating.gif",
|
||||
"displayedSize": "811 x 462",
|
||||
"actualSize": "811 x 462",
|
||||
"actualPixels": 374682,
|
||||
"expectedSize": "1622 x 924",
|
||||
"expectedPixels": 1498728
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -2060,9 +2069,23 @@
|
|||
],
|
||||
"items": [
|
||||
{
|
||||
"url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg",
|
||||
"url": "blob:http://localhost:64707/803723f3-114a-4dbd-ad67-c44f8174ef58",
|
||||
"node": {
|
||||
"type": "node"
|
||||
"type": "node",
|
||||
"path": "3,HTML,1,BODY,63,IMG",
|
||||
"selector": "body > img",
|
||||
"nodeLabel": "img",
|
||||
"snippet": "<img src=\"blob:http://localhost:64707/803723f3-114a-4dbd-ad67-c44f8174ef58\">"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "filesystem:http://localhost:64707/temporary/empty-0.4587600445763731.png",
|
||||
"node": {
|
||||
"type": "node",
|
||||
"path": "3,HTML,1,BODY,72,IMG",
|
||||
"selector": "body > img",
|
||||
"nodeLabel": "img",
|
||||
"snippet": "<img src=\"filesystem:http://localhost:64707/temporary/empty-0.4587600445763731.png\">"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -443,8 +443,6 @@ declare global {
|
|||
* See https://html.spec.whatwg.org/multipage/images.html#pixel-density-descriptor
|
||||
*/
|
||||
usesSrcSetDensityDescriptor: boolean;
|
||||
/** The size of the underlying image file in bytes. 0 if the file could not be identified. */
|
||||
resourceSize: number;
|
||||
/** The MIME type of the underlying image file. */
|
||||
mimeType?: string;
|
||||
/** The loading attribute of the image. */
|
||||
|
|
Загрузка…
Ссылка в новой задаче