Replace TotalRequests and SmallRequests rules
This commit is contained in:
@@ -236,3 +236,9 @@
|
||||
border: 1px solid #000;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
.smallPreview {
|
||||
max-height: 1.5em;
|
||||
max-width: 4em;
|
||||
border: 1px solid #000;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
@@ -259,4 +259,11 @@
|
||||
border: 1px solid #000;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.smallPreview {
|
||||
max-height: 1.5em;
|
||||
max-width: 4em;
|
||||
border: 1px solid #000;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
@@ -269,6 +269,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="policyName === 'totalRequests'">
|
||||
<h3>Requests by MIME type</h3>
|
||||
<div ng-repeat="(type, requests) in rule.offendersObj.list.byType">
|
||||
<h3><ng-pluralize count="requests.length" when="{'0': 'No ' + type + ' request', 'one': '1 ' + type + ' request', 'other': '{} ' + type + ' requests'}"></ng-pluralize></h3>
|
||||
<p ng-if="type == 'css' && requests.length > 2">Reduce the number of stylesheets by concatenating them.</p>
|
||||
<p ng-if="type == 'js' && requests.length > 3">Reduce the number of scripts by concatenating them.</p>
|
||||
<p ng-if="type == 'image' && requests.length > 5">Reduce the number of images by lazyloading them or by spriting them.</p>
|
||||
<p ng-if="type == 'webfont' && requests.length > 1">Fonts are generally loaded on the critical path of the head. Load as few as possible.</p>
|
||||
<p ng-if="type == 'other' && requests.length > 0">They can be Flash, XML, music or any undetected format.</p>
|
||||
<div class="offendersTable">
|
||||
<div ng-repeat="request in requests track by $index">
|
||||
<div><url-link url="request" max-length="100"></url-link></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="policyName === 'smallRequests'">
|
||||
<div ng-repeat="(type, requests) in rule.offendersObj.list.byType">
|
||||
<h3><ng-pluralize count="requests.length" when="{'0': 'small ' + type + ' file', 'one': '1 small ' + type + ' file', 'other': '{} small ' + type + ' files'}"></ng-pluralize></h3>
|
||||
<p ng-if="type == 'css' && requests.length > 0">Try to inline these styles in the head of the HTML or to merge them with other files.</p>
|
||||
<p ng-if="type == 'js' && requests.length > 0">Try to inline these scripts in the HTML or merge them with other files.</p>
|
||||
<p ng-if="type == 'image' && requests.length > 0">Try to inline these images (with base64 encoding for most image types except SVG that don't need base64 encoding). You can also create sprites.</p>
|
||||
<div class="table">
|
||||
<div class="headers">
|
||||
<div ng-if="type == 'image'">Preview</div>
|
||||
<div>File</div>
|
||||
<div>Weight (bytes)</div>
|
||||
</div>
|
||||
<div ng-repeat="request in requests track by $index">
|
||||
<div ng-if="type == 'image'"><img ng-src="{{request.url}}" class="smallPreview checker" /></div>
|
||||
<div><url-link url="request.url" max-length="100"></url-link></div>
|
||||
<div>{{request.size}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="policyName === 'DOMaccesses'">
|
||||
<h3>{{rule.value}} offenders</h3>
|
||||
Please open the <a href="/result/{{runId}}/timeline">JS timeline</a>
|
||||
|
||||
+12
-151
@@ -892,162 +892,23 @@ var policies = {
|
||||
"hasOffenders": true,
|
||||
"unit": 'bytes'
|
||||
},
|
||||
"requests": {
|
||||
"tool": "phantomas",
|
||||
"totalRequests": {
|
||||
"tool": "weightChecker",
|
||||
"label": "Total requests number",
|
||||
"message": "<p>This is one of the most important performance rule. Every request is slowing down the page loading.</p><p>There are several technics to reduce their number:<ul><li>Concatenate JS files</li><li>Concatenate CSS files</li><li>Embed or inline small JS or CSS files in the HTML</li><li>Create sprites or icon fonts</li><li>Base64 encode small images in HTML or stylesheets</li><li>Use lazyloading for images</li></ul></p>",
|
||||
"isOkThreshold": 15,
|
||||
"isBadThreshold": 100,
|
||||
"isAbnormalThreshold": 200,
|
||||
"hasOffenders": true,
|
||||
"takeOffendersFrom": ["htmlCount", "jsCount", "cssCount", "imageCount", "webfontCount", "videoCount", "jsonCount", "otherCount"],
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders
|
||||
.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
}).sort(function(a, b) {
|
||||
return (b.file < a.file) ? 1 : (b.file > a.file) ? -1 : 0;
|
||||
})
|
||||
};
|
||||
}
|
||||
"isAbnormalThreshold": 180,
|
||||
"hasOffenders": true
|
||||
},
|
||||
"htmlCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "Document count",
|
||||
"message": "<p>The number of HTML pages requests, HTML fragments or iframes.</p>",
|
||||
"isOkThreshold": 10,
|
||||
"isBadThreshold": 20,
|
||||
"isAbnormalThreshold": 30,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"jsCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "Script count",
|
||||
"message": "<p>Reduce the number of scripts by concatenating them.</p>",
|
||||
"isOkThreshold": 5,
|
||||
"isBadThreshold": 15,
|
||||
"isAbnormalThreshold": 30,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"cssCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "CSS count",
|
||||
"message": "<p>Reduce the number of stylesheets by concatenating them.</p>",
|
||||
"isOkThreshold": 3,
|
||||
"isBadThreshold": 10,
|
||||
"isAbnormalThreshold": 22,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"imageCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "Image count",
|
||||
"message": "<p>Reduce the number of images by lazyloading them, by spriting them or by creating an icons font.</p>",
|
||||
"isOkThreshold": 15,
|
||||
"isBadThreshold": 40,
|
||||
"isAbnormalThreshold": 70,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"webfontCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "Font count",
|
||||
"message": "<p>Fonts are loaded on the critical path of the head. Load as few as possible.</p>",
|
||||
"isOkThreshold": 1,
|
||||
"isBadThreshold": 3,
|
||||
"isAbnormalThreshold": 5,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"videoCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "Video count",
|
||||
"message": "<p>The number of videos loaded.</p>",
|
||||
"isOkThreshold": 1,
|
||||
"isBadThreshold": 5,
|
||||
"isAbnormalThreshold": 15,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"jsonCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "JSON count",
|
||||
"message": "<p>The number of AJAX requests to JSON files or webservices.</p>",
|
||||
"isOkThreshold": 2,
|
||||
"isBadThreshold": 10,
|
||||
"isAbnormalThreshold": 25,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
"otherCount": {
|
||||
"tool": "phantomas",
|
||||
"label": "Other types of requests",
|
||||
"message": "<p>They can be Flash, XML, music or any unknown format.</p>",
|
||||
"isOkThreshold": 5,
|
||||
"isBadThreshold": 20,
|
||||
"isAbnormalThreshold": 40,
|
||||
"hasOffenders": true,
|
||||
"offendersTransformFn": function(offenders) {
|
||||
return {
|
||||
count: offenders.length,
|
||||
list: offenders.map(function(offender) {
|
||||
return offendersHelpers.fileWithSizePattern(offender);
|
||||
})
|
||||
};
|
||||
}
|
||||
"smallRequests": {
|
||||
"tool": "weightChecker",
|
||||
"label": "Small requests",
|
||||
"message": "<p>List of all requests that are less than 2 KB. Try to merge them with other files.</p>",
|
||||
"isOkThreshold": 4,
|
||||
"isBadThreshold": 30,
|
||||
"isAbnormalThreshold": 50,
|
||||
"hasOffenders": true
|
||||
},
|
||||
"smallJsFiles": {
|
||||
"tool": "phantomas",
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"requests": {
|
||||
"label": "Requests",
|
||||
"policies": {
|
||||
"requests": 5,
|
||||
"totalRequests": 5,
|
||||
"domains": 3,
|
||||
"notFound": 3,
|
||||
"multipleRequests": 2,
|
||||
|
||||
@@ -67,13 +67,17 @@ var WeightChecker = function() {
|
||||
endTime = Date.now();
|
||||
debug('Redownload took %d ms', endTime - startTime);
|
||||
|
||||
var metrics = {};
|
||||
var offenders = {};
|
||||
|
||||
// Count requests
|
||||
offenders.totalRequests = listRequestsByType(results);
|
||||
metrics.totalRequests = offenders.totalRequests.total;
|
||||
|
||||
// Remove unwanted requests (redirections, about:blank)
|
||||
results = results.filter(function(result) {
|
||||
return (result !== null && result.weightCheck && result.weightCheck.bodySize > 0);
|
||||
});
|
||||
|
||||
var metrics = {};
|
||||
var offenders = {};
|
||||
|
||||
|
||||
// Total weight
|
||||
@@ -92,6 +96,10 @@ var WeightChecker = function() {
|
||||
offenders.gzipCompression = listFilesNotGzipped(results);
|
||||
metrics.gzipCompression = offenders.gzipCompression.totalGain;
|
||||
|
||||
// Small requests
|
||||
offenders.smallRequests = listSmallRequests(results);
|
||||
metrics.smallRequests = offenders.smallRequests.total;
|
||||
|
||||
data.toolsResults.weightChecker = {
|
||||
metrics: metrics,
|
||||
offenders: offenders
|
||||
@@ -249,6 +257,57 @@ var WeightChecker = function() {
|
||||
return results;
|
||||
}
|
||||
|
||||
function listRequestsByType(requests) {
|
||||
var results = {
|
||||
total: 0,
|
||||
byType: {
|
||||
html: [],
|
||||
css: [],
|
||||
js: [],
|
||||
json: [],
|
||||
image: [],
|
||||
video: [],
|
||||
webfont: [],
|
||||
other: []
|
||||
}
|
||||
};
|
||||
|
||||
requests.forEach(function(req) {
|
||||
if (req.url !== 'about:blank') {
|
||||
var type = req.type || 'other';
|
||||
results.byType[type].push(req.url);
|
||||
results.total ++;
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function listSmallRequests(requests) {
|
||||
var results = {
|
||||
total: 0,
|
||||
byType: {
|
||||
css: [],
|
||||
js: [],
|
||||
image: []
|
||||
}
|
||||
};
|
||||
|
||||
requests.forEach(function(req) {
|
||||
if (req.weightCheck.bodySize > 0 && req.weightCheck.bodySize < 2048) {
|
||||
if (req.isCSS || req.isJS || req.isImage) {
|
||||
results.byType[req.type].push({
|
||||
url: req.url,
|
||||
size: req.weightCheck.bodySize
|
||||
});
|
||||
results.total ++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
function redownloadEntry(entry) {
|
||||
var deferred = Q.defer();
|
||||
|
||||
@@ -136,6 +136,23 @@ describe('weightChecker', function() {
|
||||
data.toolsResults.weightChecker.offenders.fileMinification.totalGain.should.be.above(0);
|
||||
data.toolsResults.weightChecker.offenders.fileMinification.files.length.should.equal(2);
|
||||
|
||||
data.toolsResults.weightChecker.metrics.should.have.a.property('totalRequests').that.equals(6);
|
||||
data.toolsResults.weightChecker.offenders.should.have.a.property('totalRequests');
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.html.length.should.equal(1);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.js.length.should.equal(2);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.css.length.should.equal(1);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.image.length.should.equal(2);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.json.length.should.equal(0);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.webfont.length.should.equal(0);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.video.length.should.equal(0);
|
||||
data.toolsResults.weightChecker.offenders.totalRequests.byType.other.length.should.equal(0);
|
||||
|
||||
data.toolsResults.weightChecker.metrics.should.have.a.property('smallRequests').that.equals(0);
|
||||
data.toolsResults.weightChecker.offenders.should.have.a.property('smallRequests');
|
||||
data.toolsResults.weightChecker.offenders.smallRequests.byType.js.length.should.equal(0);
|
||||
data.toolsResults.weightChecker.offenders.smallRequests.byType.css.length.should.equal(0);
|
||||
data.toolsResults.weightChecker.offenders.smallRequests.byType.image.length.should.equal(0);
|
||||
|
||||
done();
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user