Skip to content

Commit

Permalink
Review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
wardpeet committed Apr 12, 2018
1 parent 3cffdd8 commit a08008f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
*/
'use strict';

const Audit = require('../audit');
const WebInspector = require('../../lib/web-inspector');
const ByteEfficiencyAudit = require('./byte-efficiency-audit');

// the threshold for the size of GIFs wich we flag as unoptimized
const GIF_BYTE_THRESHOLD = 100 * 1024;

class UsesOptimizedAnimatedImages extends Audit {
class UsesOptimizedAnimatedImages extends ByteEfficiencyAudit {
/**
* @return {!AuditMeta}
*/
static get meta() {
return {
name: 'uses-optimized-animated-images',
informative: true,
scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
description: 'Use a video formats for animated content',
helpText: 'Large GIFs are inefficient for delivering animated content. Consider using ' +
'MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save ' +
Expand All @@ -30,44 +30,52 @@ class UsesOptimizedAnimatedImages extends Audit {
};
}

/**
* Calculate savings percentage
* @param {number} bytes
* @see https://github.com/GoogleChrome/lighthouse/issues/4696#issuecomment-380296510} bytes
*/
static getPercentSavings(bytes) {
return (29.1 * Math.log10(bytes) - 100.7) / 100;
}

/**
* @param {!Artifacts} artifacts
* @return {!AuditResult}
*/
static async audit(artifacts) {
static async audit_(artifacts) {
const devtoolsLogs = artifacts.devtoolsLogs[UsesOptimizedAnimatedImages.DEFAULT_PASS];

const networkRecords = await artifacts.requestNetworkRecords(devtoolsLogs);
const unoptimizedContent = networkRecords.filter(
record => record.mimeType === 'image/gif' &&
record._resourceType === WebInspector.resourceTypes.Image &&
record.transferSize > GIF_BYTE_THRESHOLD
record.resourceSize > GIF_BYTE_THRESHOLD
);

const results = unoptimizedContent.map(record => {
return {
url: record.url,
transferSize: record.transferSize,
totalBytes: record.resourceSize,
wastedBytes: record.resourceSize * UsesOptimizedAnimatedImages.getPercentSavings(record.resourceSize),
};
});

const headings = [
{key: 'url', itemType: 'url', text: 'Url'},
{key: 'url', itemType: 'url', text: 'URL'},
{
key: 'transferSize',
key: 'totalBytes',
itemType: 'bytes',
displayUnit: 'kb',
granularity: 1,
text: 'Transfer Size',
},
{key: 'wastedBytes', itemType: 'bytes', displayUnit: 'kb', granularity: 1, text: 'Byte Savings'},
];
const summary = {};
const details = Audit.makeTableDetails(headings, results, summary);

return {
score: Number(results.length === 0),
rawValue: results.length === 0,
details,
results,
headings,
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/config/default-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ module.exports = {
{id: 'time-to-first-byte', weight: 0, group: 'perf-hint'},
{id: 'redirects', weight: 0, group: 'perf-hint'},
{id: 'uses-rel-preload', weight: 0, group: 'perf-hint'},
{id: 'uses-optimized-animated-images', weight: 0, group: 'perf-hint'},
{id: 'total-byte-weight', weight: 0, group: 'perf-info'},
{id: 'uses-long-cache-ttl', weight: 0, group: 'perf-info'},
{id: 'dom-size', weight: 0, group: 'perf-info'},
Expand All @@ -293,7 +294,6 @@ module.exports = {
{id: 'screenshot-thumbnails', weight: 0},
{id: 'mainthread-work-breakdown', weight: 0, group: 'perf-info'},
{id: 'font-display', weight: 0, group: 'perf-info'},
{id: 'uses-optimized-animated-images', weight: 0, group: 'perf-info'},
],
},
'pwa': {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,65 +17,64 @@ describe('Page uses videos for animated GIFs', () => {
{
_resourceType: WebInspector.resourceTypes.Image,
mimeType: 'image/gif',
transferSize: 100240,
resourceSize: 100240,
url: 'https://example.com/example.gif',
},
{
_resourceType: WebInspector.resourceTypes.Image,
mimeType: 'image/gif',
transferSize: 110000,
resourceSize: 110000,
url: 'https://example.com/example2.gif',
},
];
const artifacts = {
devtoolsLogs: {[UsesOptimizedAnimatedImages.DEFAULT_PASS]: []},
requestNetworkRecords: () => Promise.resolve(networkRecords),
};

const {score, rawValue, details} = await UsesOptimizedAnimatedImages.audit(artifacts);
assert.equal(score, 0);
assert.equal(rawValue, 0);
assert.equal(details.items.length, 1);
const {results} = await UsesOptimizedAnimatedImages.audit_(artifacts);
assert.equal(results.length, 1);
assert.equal(results[0].url, 'https://example.com/example2.gif');
assert.equal(results[0].totalBytes, 110000);
assert.equal(Math.round(results[0].wastedBytes), 50605);
});

it(`shouldn't flag content that looks like a gif but isn't`, async () => {
const networkRecords = [
{
mimeType: 'image/gif',
_resourceType: WebInspector.resourceTypes.Media,
transferSize: 150000,
resourceSize: 150000,
},
];
const artifacts = {
devtoolsLogs: {[UsesOptimizedAnimatedImages.DEFAULT_PASS]: []},
requestNetworkRecords: () => Promise.resolve(networkRecords),
};

const {score, rawValue, details} = await UsesOptimizedAnimatedImages.audit(artifacts);
assert.equal(score, 1);
assert.equal(rawValue, 1);
assert.equal(details.items.length, 0);
const {results} = await UsesOptimizedAnimatedImages.audit_(artifacts);
assert.equal(results.length, 0);
});

it(`shouldn't flag non gif content`, async () => {
const networkRecords = [
{
_resourceType: WebInspector.resourceTypes.Document,
mimeType: 'text/html',
transferSize: 150000,
resourceSize: 150000,
},
{
_resourceType: WebInspector.resourceTypes.Stylesheet,
mimeType: 'text/css',
transferSize: 150000,
resourceSize: 150000,
},
];
const artifacts = {
devtoolsLogs: {[UsesOptimizedAnimatedImages.DEFAULT_PASS]: []},
requestNetworkRecords: () => Promise.resolve(networkRecords),
};

const {score, rawValue, details} = await UsesOptimizedAnimatedImages.audit(artifacts);
assert.equal(score, 1);
assert.equal(rawValue, 1);
assert.equal(details.items.length, 0);
const {results} = await UsesOptimizedAnimatedImages.audit_(artifacts);
assert.equal(results.length, 0);
});
});

0 comments on commit a08008f

Please sign in to comment.