core(image-elements): remove resourceSize property (#11733)

This commit is contained in:
Adriana Ixba 2020-12-07 12:57:19 -06:00 коммит произвёл GitHub
Родитель 2fa473fe8d
Коммит c051eebe4f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 434 добавлений и 109 удалений

Просмотреть файл

@ -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\">"
}
}
]

2
types/artifacts.d.ts поставляемый
Просмотреть файл

@ -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. */