New DOMaccess agregated form + new score category JS complexity

This commit is contained in:
Gaël Métais
2020-11-24 00:18:55 +01:00
parent 5bf3bd7ce5
commit ffd9efeb98
6 changed files with 112 additions and 33 deletions
@@ -93,6 +93,13 @@
};
});
offendersDirectives.filter('lastDOMNode', function() {
return function(str) {
var splited = str.split(' > ');
return splited[splited.length - 1];
};
});
function getBacktraceHTML(backtrace) {
var html = '';
var parsedBacktrace = parseBacktrace(backtrace);
+31 -1
View File
@@ -30,7 +30,7 @@
<p>This rule reached the abnormality threshold, which means there is a real problem you should care about.</p>
</div>
<div class="offenders" ng-if="rule.policy.hasOffenders">
<h3 ng-if="rule.offendersObj.count >= 0"><ng-pluralize count="rule.offendersObj.count" when="{'0': 'No offenders', 'one': '1 offender', 'other': '{} offenders'}"></ng-pluralize></h3>
<h3 ng-if="rule.offendersObj.count >= 0"><ng-pluralize count="rule.offendersObj.count" when="{'0': 'No offender', 'one': '1 offender', 'other': '{} offenders'}"></ng-pluralize></h3>
<div ng-if="rule.offendersObj.list" class="offendersTable">
<div ng-repeat="offender in rule.offendersObj.list track by $index">
@@ -264,6 +264,36 @@
</div>
</div>
<div ng-if="policyName === 'DOMaccesses'">
<div ng-repeat="(type, list) in rule.offendersObj.list.byType">
<h3>
<ng-pluralize count="list.length" when="{'0': 'No offender', 'one': '1 offender', 'other': '{} offenders'}"></ng-pluralize> from
<span ng-if="type === 'DOMqueriesById'">getElementById()</span>
<span ng-if="type === 'DOMqueriesByTagName'">getElementsByTagName()</span>
<span ng-if="type === 'DOMqueriesByClassName'">getElementsByClassName()</span>
<span ng-if="type === 'DOMqueriesByQuerySelectorAll'">querySelector() or querySelectorAll()</span>
<span ng-if="type === 'DOMinserts'">appendChild() or insertBefore()</span>
<span ng-if="type === 'DOMmutationsInserts'">added nodes</span>
<span ng-if="type === 'DOMmutationsRemoves'">removed nodes</span>
<span ng-if="type === 'DOMmutationsAttributes'">attribute changes</span>
<span ng-if="type === 'eventsBound'">addEventListener()</span>
</h3>
<div class="offendersTable">
<div ng-repeat="access in list">
<div ng-if="type === 'DOMqueriesById'">#{{access.id}}</div>
<div ng-if="type === 'DOMqueriesByTagName'">{{access.tag}} <b>on</b> <span title="{{access.node}}">{{access.node | lastDOMNode}}</span></div>
<div ng-if="type === 'DOMqueriesByClassName'">.{{access.class}} <b>on</b> <span title="{{access.node}}">{{access.node | lastDOMNode}}</span></div>
<div ng-if="type === 'DOMqueriesByQuerySelectorAll'">{{access.selector}} <b>on</b> <span title="{{access.node}}">{{access.node | lastDOMNode}}</span></div>
<div ng-if="type === 'DOMinserts'"><span title="{{access.append}}">{{access.append | lastDOMNode}}</span> <b>added to</b> <span title="{{access.node}}">{{access.node | lastDOMNode}}</span></div>
<div ng-if="type === 'DOMmutationsInserts'">{{access.node}} <b>added to</b> {{access.target}}</div>
<div ng-if="type === 'DOMmutationsRemoves'">{{access.node}} <b>removed from</b> {{access.target}}</div>
<div ng-if="type === 'DOMmutationsAttributes'">{{access.attribute}} <b>changed on</b> {{access.node}}</div>
<div ng-if="type === 'eventsBound'">{{access.eventType}} <b>on</b> <span title="{{access.path}}">{{access.path | lastDOMNode}}</span></div>
</div>
</div>
</div>
</div>
<div ng-if="policyName === 'imageOptimization'">
<h3 ng-if="rule.value > 0">{{rule.value | bytes}} could be saved on <ng-pluralize count="rule.offendersObj.list.images.length" when="{'one': '1 image', 'other': '{} images'}"></ng-pluralize></h3>
<div class="imageOffenders">
+8 -31
View File
@@ -46,37 +46,14 @@ var policies = {
"isAbnormalThreshold": 50,
"hasOffenders": true
},
"DOMqueriesAvoidable": {
"tool": "phantomas",
"label": "Duplicated DOM queries",
"message": "<p>This is the number of queries that could be avoided by removing all duplicated queries.</p><p>Simply save the result of a query in a variable. Ok it is not always simple, especially with third-party scripts, but at least do it with your own code.</p>",
"isOkThreshold": 0,
"isBadThreshold": 300,
"isAbnormalThreshold": 600,
"hasOffenders": true,
"takeOffendersFrom": "DOMqueriesDuplicated",
"offendersTransformFn": function(offenders) {
return {
count: offenders.length,
list: offenders.map(function(offender) {
var parts = /^[^"]* ?"(.*)" ?with ?(.*) ?\(in ?context ?(.*)\): ?(.*)\s?queries$/.exec(offender);
if (!parts) {
debug('DOMqueriesAvoidable offenders transform function error with "%s"', offender);
return {
parseError: offender
};
}
return {
query: parts[1],
context: offendersHelpers.domPathToDomElementObj(parts[3]),
fn: parts[2],
count: parseInt(parts[4], 10)
};
})
};
}
"DOMaccesses": {
"tool": "domAccessAgregator",
"label": "DOM access",
"message": "<p>This metric estimates the number of times the JavaScript reads, changes or binds the DOM.</p><p>The more your JavaScript code accesses the DOM, the slower the page will load.</p><p>Try, as much as possible, to have an HTML page fully generated by the server instead of making changes with JS.</p><p>Try to reduce the number of queries by refactoring your JavaScript code.</p><p>Binding too many events also has a cost.</p>",
"isOkThreshold": 500,
"isBadThreshold": 2500,
"isAbnormalThreshold": 5000,
"hasOffenders": true
},
"eventsScrollBound": {
"tool": "phantomas",
+9 -1
View File
@@ -32,8 +32,15 @@
"DOMidDuplicated": 1
}
},
"javascriptComplexity": {
"label": "JS complexity",
"policies": {
"DOMaccesses": 4,
"eventsScrollBound": 1
}
},
"badJavascript": {
"label": "Bad JavaScript",
"label": "Bad JS",
"policies": {
"jsErrors": 1,
"documentWriteCalls": 2,
@@ -100,6 +107,7 @@
"pageWeight": 3,
"requests": 3,
"domComplexity": 2,
"javascriptComplexity": 2,
"badJavascript": 2,
"jQuery": 1,
"cssSyntaxError": 1,
+4
View File
@@ -3,6 +3,7 @@ var debug = require('debug')('ylt:runner');
var phantomasWrapper = require('./tools/phantomas/phantomasWrapper');
var colorDiff = require('./tools/colorDiff');
var domAccessAgregator = require('./tools/domAccessAgregator');
var mediaQueriesChecker = require('./tools/mediaQueriesChecker');
var isHttp2 = require('./tools/isHttp2');
var redownload = require('./tools/redownload/redownload');
@@ -27,6 +28,9 @@ var Runner = function(params) {
.then(function(phantomasResults) {
data.toolsResults.phantomas = phantomasResults;
// Mix all DOM Access metrics together
data = domAccessAgregator.agregate(data);
// Compare colors
data = colorDiff.compareAllColors(data);
+53
View File
@@ -0,0 +1,53 @@
var debug = require('debug')('ylt:domAccessAgregator');
var domAccessAgregator = function() {
'use strict';
this.agregate = function(data) {
debug('Starting to agregate DOM Accesses...');
let count = 0;
let offenders = {
byType: {}
};
const metricsToGather = [
'DOMqueriesById',
'DOMqueriesByTagName',
'DOMqueriesByClassName',
'DOMqueriesByQuerySelectorAll',
'DOMinserts',
'DOMmutationsInserts',
'DOMmutationsRemoves',
'DOMmutationsAttributes',
'eventsBound'
];
metricsToGather.forEach(key => {
if (data.toolsResults.phantomas.metrics[key]) {
count += data.toolsResults.phantomas.metrics[key];
}
offenders.byType[key] = [];
if (data.toolsResults.phantomas.offenders[key]) {
offenders.byType[key] = data.toolsResults.phantomas.offenders[key];
}
});
data.toolsResults.domAccessAgregator = {
metrics: {
DOMaccesses: count
},
offenders: {
DOMaccesses: offenders
}
};
debug('Done agregating DOM Accesses.');
return data;
};
};
module.exports = new domAccessAgregator();