From 4e6a88abec730e836c822b825848f8807f5de13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20M=C3=A9tais?= Date: Mon, 11 May 2015 19:43:15 +0200 Subject: [PATCH] New jQuery usage rule --- front/src/views/rule.html | 4 +++ lib/metadata/policies.js | 13 ++++++++-- lib/metadata/scoreProfileGeneric.json | 11 ++++---- lib/tools/jsExecutionTransformer.js | 37 ++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/front/src/views/rule.html b/front/src/views/rule.html index 6ec11ab..5badf0a 100644 --- a/front/src/views/rule.html +++ b/front/src/views/rule.html @@ -79,6 +79,10 @@ +
+ Function {{offender.functionName}} used {{offender.count}} times +
+
{{offender.writeFn}} diff --git a/lib/metadata/policies.js b/lib/metadata/policies.js index b7eade5..f7877a5 100644 --- a/lib/metadata/policies.js +++ b/lib/metadata/policies.js @@ -66,7 +66,7 @@ var policies = { }; } }, - "DOMaccesses": { + /*"DOMaccesses": { "tool": "jsExecutionTransformer", "label": "DOM access", "message": "

TODO

TODO

", @@ -74,7 +74,7 @@ var policies = { "isBadThreshold": 2000, "isAbnormalThreshold": 3000, "hasOffenders": false - }, + },*/ "DOMinserts": { "tool": "phantomas", "label": "DOM inserts", @@ -430,6 +430,15 @@ var policies = { "isAbnormalThreshold": 2, "hasOffenders": true }, + "jQueryFunctionsUsed": { + "tool": "jsExecutionTransformer", + "label": "jQuery usage", + "message": "

This is the number of different jQuery functions called on load. This rule is not trying to blame you for using jQuery too much, but the opposite.

If only a few functions are used, why not trying to get rid of jQuery? Have a look at http://youmightnotneedjquery.com.

", + "isOkThreshold": 15, + "isBadThreshold": 6, + "isAbnormalThreshold": 0, + "hasOffenders": true + }, "cssParsingErrors": { "tool": "phantomas", "label": "CSS syntax error", diff --git a/lib/metadata/scoreProfileGeneric.json b/lib/metadata/scoreProfileGeneric.json index e682259..df7400e 100644 --- a/lib/metadata/scoreProfileGeneric.json +++ b/lib/metadata/scoreProfileGeneric.json @@ -35,11 +35,12 @@ "globalVariables": 0.5 } }, - "jQueryVersion": { - "label": "jQuery version", + "jQuery": { + "label": "jQuery", "policies": { - "jQueryVersion": 5, - "jQueryVersionsLoaded": 0.1 + "jQueryVersion": 10, + "jQueryVersionsLoaded": 1, + "jQueryFunctionsUsed": 1 } }, "cssComplexity": { @@ -109,7 +110,7 @@ "domManipulations": 2, "scroll": 1, "badJavascript": 1, - "jQueryVersion": 1, + "jQuery": 1, "cssSyntaxError": 1, "cssComplexity": 1, "badCSS": 1, diff --git a/lib/tools/jsExecutionTransformer.js b/lib/tools/jsExecutionTransformer.js index 577d255..b15ccd1 100644 --- a/lib/tools/jsExecutionTransformer.js +++ b/lib/tools/jsExecutionTransformer.js @@ -1,12 +1,14 @@ var debug = require('debug')('ylt:jsExecutionTransformer'); -var offendersHelpers = require('../offendersHelpers'); +var offendersHelpers = require('../offendersHelpers'); +var Collection = require('./phantomas/custom_modules/util/collection'); var jsExecutionTransformer = function() { this.transform = function(data) { var javascriptExecutionTree = {}; var scrollExecutionTree = {}; + var jQueryFunctionsCollection = new Collection(); var metrics = { DOMaccesses: 0, @@ -17,6 +19,10 @@ var jsExecutionTransformer = function() { jQueryNotDelegatedEvent: 0 }; + var offenders = { + + }; + try { debug('Starting JS execution transformation'); @@ -44,6 +50,7 @@ var jsExecutionTransformer = function() { if (node.data.type.indexOf('jQuery - ') === 0) { metrics.jQueryCalls ++; + jQueryFunctionsCollection.push(node.data.type); } // Mark errors with an error flag @@ -78,14 +85,32 @@ var jsExecutionTransformer = function() { // Count the number of DOM accesses, by counting the tree leafs metrics.DOMaccesses += countTreeLeafs(node); }); + + // Count the number of different jQuery functions called + if (data.toolsResults.phantomas.metrics.jQueryVersionsLoaded) { + metrics.jQueryFunctionsUsed = 0; + offenders.jQueryFunctionsUsed = []; + + jQueryFunctionsCollection.sort().forEach(function(fnName, cnt) { + if (fnName === 'jQuery - find') { + fnName = 'jQuery - $'; + } + metrics.jQueryFunctionsUsed ++; + offenders.jQueryFunctionsUsed.push({ + functionName: fnName.substring(9), + count: cnt + }); + }); + } + } debug('JS execution transformation complete'); debug('Starting scroll execution transformation'); - scrollExecutionTree = JSON.parse(data.toolsResults.phantomas.offenders.scrollExecutionTree[0]); - if (scrollExecutionTree.children) { - scrollExecutionTree.children.forEach(function(node) { + offenders.scrollExecutionTree = JSON.parse(data.toolsResults.phantomas.offenders.scrollExecutionTree[0]); + if (offenders.scrollExecutionTree.children) { + offenders.scrollExecutionTree.children.forEach(function(node) { // Mark a event flag if (['documentScroll', 'windowScroll', 'window.onscroll'].indexOf(node.data.type) >= 0) { @@ -109,9 +134,7 @@ var jsExecutionTransformer = function() { data.toolsResults.jsExecutionTransformer = { metrics: metrics, - offenders: { - DOMaccessesOnScroll: scrollExecutionTree - } + offenders: offenders }; return data;