diff --git a/front/src/views/rule.html b/front/src/views/rule.html index 769f378..99aca48 100644 --- a/front/src/views/rule.html +++ b/front/src/views/rule.html @@ -335,6 +335,17 @@ +
+
+

A file of {{offender.weight | bytes}} is loaded {{offender.urls.length}} times:

+
+
+
+
+
+
+
+

diff --git a/lib/metadata/policies.js b/lib/metadata/policies.js index 0f52db5..65e7d3f 100644 --- a/lib/metadata/policies.js +++ b/lib/metadata/policies.js @@ -994,14 +994,17 @@ var policies = { "isAbnormalThreshold": 20, "hasOffenders": true }, - "multipleRequests": { - "tool": "phantomas", - "label": "Duplicated requests", - "message": "

This only happens when the asset has no cache and is requested more than once on the same page. Be very careful about it.

", + "identicalFiles": { + "tool": "redownload", + "label": "Identical content", + "message": "

This is the number of requests that could be avoided, because of downloaded files that have the same content but are loaded from different URLs.

Try to load them from the same URL.

", "isOkThreshold": 0, - "isBadThreshold": 3, - "isAbnormalThreshold": 10, - "hasOffenders": true + "isBadThreshold": 5, + "isAbnormalThreshold": 15, + "hasOffenders": true, + "offendersTransformFn": function(offenders) { + return offenders; + } }, "emptyRequests": { "tool": "redownload", diff --git a/lib/metadata/scoreProfileGeneric.json b/lib/metadata/scoreProfileGeneric.json index ccd5512..958db6a 100644 --- a/lib/metadata/scoreProfileGeneric.json +++ b/lib/metadata/scoreProfileGeneric.json @@ -15,7 +15,7 @@ "totalRequests": 5, "domains": 3, "notFound": 3, - "multipleRequests": 2, + "identicalFiles": 2, "emptyRequests": 3, "smallRequests": 1, "lazyLoadableImagesBelowTheFold": 2, diff --git a/lib/tools/redownload/redownload.js b/lib/tools/redownload/redownload.js index 693eb23..e5a72ce 100644 --- a/lib/tools/redownload/redownload.js +++ b/lib/tools/redownload/redownload.js @@ -11,6 +11,7 @@ var http = require('http'); var zlib = require('zlib'); var async = require('async'); var request = require('request'); +var md5 = require('md5'); var imageOptimizer = require('./imageOptimizer'); var fileMinifier = require('./fileMinifier'); @@ -106,9 +107,9 @@ var Redownload = function() { metrics.emptyRequests = offenders.emptyRequests.length; - // Now emove unwanted responses (redirections) + // Now remove unwanted responses (redirections and empty files) results = results.filter(function(result) { - return (result.status < 300 || result.status >= 400); + return ((result.status < 300 || result.status >= 400) && result.weightCheck.bodySize > 0); }); @@ -128,6 +129,11 @@ var Redownload = function() { offenders.smallRequests = listSmallRequests(results); metrics.smallRequests = offenders.smallRequests.total; + // Detect identical files + offenders.identicalFiles = listIdenticalFiles(results); + metrics.identicalFiles = offenders.identicalFiles.avoidableRequests; + + data.toolsResults.redownload = { metrics: metrics, offenders: offenders @@ -368,6 +374,45 @@ var Redownload = function() { return results; } + function listIdenticalFiles(requests) { + var hashes = {}; + var list = []; + var avoidableRequestsCount = 0; + + requests.forEach(function(req) { + var requestHash = md5(req.weightCheck.body); + + // Try to exclude tracking pixels + if (req.weightCheck.bodySize < 80 && req.type === 'image') { + return; + } + + if (!hashes[requestHash]) { + hashes[requestHash] = { + weight: req.weightCheck.bodySize, + urls: [] + }; + } + + if (hashes[requestHash].urls.indexOf(req.url) === -1) { + hashes[requestHash].urls.push(req.url); + } + }); + + for (var hash in hashes) { + if (hashes[hash].urls.length > 1) { + list.push(hashes[hash]); + avoidableRequestsCount += hashes[hash].urls.length - 1; + } + } + + return { + avoidableRequests: avoidableRequestsCount, + count: list.length, + list: list + }; + } + function redownloadEntry(entry, httpAuth) { var deferred = Q.defer(); diff --git a/package.json b/package.json index 6dc56b3..b29fa29 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "is-woff": "1.0.3", "is-woff2": "1.0.0", "lwip": "0.0.9", + "md5": "2.1.0", "meow": "3.7.0", "minimize": "2.0.0", "parse-color": "1.0.0",