From ffd9efeb986c35fd6e89ee9d2e175f5914b12588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20M=C3=A9tais?= Date: Tue, 24 Nov 2020 00:18:55 +0100 Subject: [PATCH] New DOMaccess agregated form + new score category JS complexity --- .../src/js/directives/offendersDirectives.js | 7 +++ front/src/views/rule.html | 32 ++++++++++- lib/metadata/policies.js | 39 +++----------- lib/metadata/scoreProfileGeneric.json | 10 +++- lib/runner.js | 4 ++ lib/tools/domAccessAgregator.js | 53 +++++++++++++++++++ 6 files changed, 112 insertions(+), 33 deletions(-) create mode 100644 lib/tools/domAccessAgregator.js diff --git a/front/src/js/directives/offendersDirectives.js b/front/src/js/directives/offendersDirectives.js index c2663bc..956a9cb 100644 --- a/front/src/js/directives/offendersDirectives.js +++ b/front/src/js/directives/offendersDirectives.js @@ -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); diff --git a/front/src/views/rule.html b/front/src/views/rule.html index 58a3c30..73ce778 100644 --- a/front/src/views/rule.html +++ b/front/src/views/rule.html @@ -30,7 +30,7 @@

This rule reached the abnormality threshold, which means there is a real problem you should care about.

-

+

@@ -264,6 +264,36 @@
+
+
+

+ from + getElementById() + getElementsByTagName() + getElementsByClassName() + querySelector() or querySelectorAll() + appendChild() or insertBefore() + added nodes + removed nodes + attribute changes + addEventListener() +

+
+
+
#{{access.id}}
+
{{access.tag}} on {{access.node | lastDOMNode}}
+
.{{access.class}} on {{access.node | lastDOMNode}}
+
{{access.selector}} on {{access.node | lastDOMNode}}
+
{{access.append | lastDOMNode}} added to {{access.node | lastDOMNode}}
+
{{access.node}} added to {{access.target}}
+
{{access.node}} removed from {{access.target}}
+
{{access.attribute}} changed on {{access.node}}
+
{{access.eventType}} on {{access.path | lastDOMNode}}
+
+
+
+
+

{{rule.value | bytes}} could be saved on

diff --git a/lib/metadata/policies.js b/lib/metadata/policies.js index a564345..49bf3a4 100644 --- a/lib/metadata/policies.js +++ b/lib/metadata/policies.js @@ -46,37 +46,14 @@ var policies = { "isAbnormalThreshold": 50, "hasOffenders": true }, - "DOMqueriesAvoidable": { - "tool": "phantomas", - "label": "Duplicated DOM queries", - "message": "

This is the number of queries that could be avoided by removing all duplicated queries.

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.

", - "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": "

This metric estimates the number of times the JavaScript reads, changes or binds the DOM.

The more your JavaScript code accesses the DOM, the slower the page will load.

Try, as much as possible, to have an HTML page fully generated by the server instead of making changes with JS.

Try to reduce the number of queries by refactoring your JavaScript code.

Binding too many events also has a cost.

", + "isOkThreshold": 500, + "isBadThreshold": 2500, + "isAbnormalThreshold": 5000, + "hasOffenders": true }, "eventsScrollBound": { "tool": "phantomas", diff --git a/lib/metadata/scoreProfileGeneric.json b/lib/metadata/scoreProfileGeneric.json index 5646b26..f9aa7a8 100644 --- a/lib/metadata/scoreProfileGeneric.json +++ b/lib/metadata/scoreProfileGeneric.json @@ -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, diff --git a/lib/runner.js b/lib/runner.js index c201302..f0ba25b 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -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); diff --git a/lib/tools/domAccessAgregator.js b/lib/tools/domAccessAgregator.js new file mode 100644 index 0000000..01a5472 --- /dev/null +++ b/lib/tools/domAccessAgregator.js @@ -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(); \ No newline at end of file