Browse Source

Total Weight offenders

Gaël Métais 10 years ago
parent
commit
d7ddae38e5

+ 8 - 9
bower.json

@@ -1,14 +1,13 @@
 {
 {
   "name": "yellowlabtools",
   "name": "yellowlabtools",
   "dependencies": {
   "dependencies": {
-    "angular": "~1.3.15",
-    "angular-route": "~1.3.15",
-    "angular-resource": "~1.3.15",
-    "angular-sanitize": "~1.3.15",
-    "angular-animate": "~1.3.15",
-    "angular-local-storage": "~0.2.0"
-  },
-  "resolutions": {
-    "angular": "~1.3.8"
+    "angular": "1.3.15",
+    "angular-route": "1.3.15",
+    "angular-resource": "1.3.15",
+    "angular-sanitize": "1.3.15",
+    "angular-animate": "1.3.15",
+    "angular-local-storage": "0.2.0",
+    "angular-chart.js": "0.7.1",
+    "Chart.js": "~1.0.2"
   }
   }
 }
 }

+ 11 - 0
front/src/css/rule.css

@@ -205,3 +205,14 @@
   z-index: 2;
   z-index: 2;
   border: 0.2em solid #f1c40f;
   border: 0.2em solid #f1c40f;
 }
 }
+.totalWeightPie {
+  max-width: 39em;
+  margin: 2em auto 4em;
+}
+.totalWeightPie canvas {
+  max-width: inherit;
+}
+.hugeFile {
+  font-weight: bold;
+  color: #e74c3c;
+}

+ 27 - 1
front/src/js/controllers/ruleCtrl.js

@@ -1,4 +1,13 @@
-var ruleCtrl = angular.module('ruleCtrl', []);
+var ruleCtrl = angular.module('ruleCtrl', ['chart.js']);
+
+ruleCtrl.config(['ChartJsProvider', function (ChartJsProvider) {
+    // Configure all charts
+    ChartJsProvider.setOptions({
+        animation: false,
+        colours: ['#FF5252', '#FF8A80'],
+        responsive: true
+    });
+}])
 
 
 ruleCtrl.controller('RuleCtrl', ['$scope', '$rootScope', '$routeParams', '$location', '$sce', 'Menu', 'Results', 'API', function($scope, $rootScope, $routeParams, $location, $sce, Menu, Results, API) {
 ruleCtrl.controller('RuleCtrl', ['$scope', '$rootScope', '$routeParams', '$location', '$sce', 'Menu', 'Results', 'API', function($scope, $rootScope, $routeParams, $location, $sce, Menu, Results, API) {
     $scope.runId = $routeParams.runId;
     $scope.runId = $routeParams.runId;
@@ -22,6 +31,23 @@ ruleCtrl.controller('RuleCtrl', ['$scope', '$rootScope', '$routeParams', '$locat
 
 
     function init() {
     function init() {
         $scope.rule = $scope.result.rules[$scope.policyName];
         $scope.rule = $scope.result.rules[$scope.policyName];
+
+        // Init "Total Weight" chart
+        if ($scope.policyName === 'totalWeight') {
+            $scope.weightLabels = [];
+            $scope.weightColours = ['#7ECCCC', '#A7E846', '#FF944D', '#FFE74A', '#C2A3FF', '#5A9AED', '#FF6452', '#C1C1C1'];
+            $scope.weightData = [];
+
+            var types = ['html', 'css', 'js', 'json', 'image', 'video', 'webfont', 'other'];
+            types.forEach(function(type) {
+                $scope.weightLabels.push(type);
+                $scope.weightData.push(Math.round($scope.rule.offendersObj.list.byType[type].totalWeight / 1024));
+            });
+
+            $scope.weightOptions = {
+                tooltipTemplate: '<%=label%>: <%=value%> KB'
+            };
+        }
     }
     }
 
 
     $scope.backToDashboard = function() {
     $scope.backToDashboard = function() {

+ 26 - 0
front/src/js/directives/offendersDirectives.js

@@ -856,4 +856,30 @@
         };
         };
     });
     });
 
 
+    offendersDirectives.filter('bytes', function() {
+        return function(bytes) {
+            if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) {
+                return '-';
+            }
+            
+            var kilo = bytes / 1024;
+
+            if (kilo < 100) {
+                return kilo.toFixed(1) + ' KB';
+            }
+
+            if (kilo < 1024) {
+                return kilo.toFixed(0) + ' KB';
+            }
+
+            var mega = kilo / 1024;
+
+            if (mega < 10) {
+                return mega.toFixed(2) + ' MB';
+            }
+
+            return mega.toFixed(1) + ' MB';
+        }
+    });
+
 })();
 })();

+ 14 - 0
front/src/less/rule.less

@@ -221,4 +221,18 @@
             border: 0.2em solid #f1c40f;
             border: 0.2em solid #f1c40f;
         }
         }
     }
     }
+}
+
+.totalWeightPie {
+    max-width: 39em;
+    margin: 2em auto 4em;
+
+    canvas {
+        max-width: inherit;
+    }
+}
+
+.hugeFile {
+    font-weight: bold;
+    color: #e74c3c;
 }
 }

+ 3 - 0
front/src/main.html

@@ -16,15 +16,18 @@
     <link rel="stylesheet" type="text/css" href="/css/screenshot.css">
     <link rel="stylesheet" type="text/css" href="/css/screenshot.css">
     <link rel="stylesheet" type="text/css" href="/css/timeline.css">
     <link rel="stylesheet" type="text/css" href="/css/timeline.css">
     <link rel="stylesheet" type="text/css" href="/css/about.css">
     <link rel="stylesheet" type="text/css" href="/css/about.css">
+    <link rel="stylesheet" type="text/css" href="/bower_components/angular-chart.js/dist/angular-chart.css">
     <!-- endbuild -->
     <!-- endbuild -->
 
 
     <!-- build:js /js/all.js -->
     <!-- build:js /js/all.js -->
     <script src="/bower_components/angular/angular.min.js"></script>
     <script src="/bower_components/angular/angular.min.js"></script>
+    <script src="/bower_components/Chart.js/Chart.min.js"></script>
     <script src="/bower_components/angular-route/angular-route.min.js"></script>
     <script src="/bower_components/angular-route/angular-route.min.js"></script>
     <script src="/bower_components/angular-resource/angular-resource.min.js"></script>
     <script src="/bower_components/angular-resource/angular-resource.min.js"></script>
     <script src="/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
     <script src="/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
     <script src="/bower_components/angular-animate/angular-animate.min.js"></script>
     <script src="/bower_components/angular-animate/angular-animate.min.js"></script>
     <script src="/bower_components/angular-local-storage/dist/angular-local-storage.min.js"></script>
     <script src="/bower_components/angular-local-storage/dist/angular-local-storage.min.js"></script>
+    <script src="/bower_components/angular-chart.js/dist/angular-chart.min.js"></script>
     <script src="/js/app.js"></script>
     <script src="/js/app.js"></script>
     <script src="/js/controllers/indexCtrl.js"></script>
     <script src="/js/controllers/indexCtrl.js"></script>
     <script src="/js/controllers/dashboardCtrl.js"></script>
     <script src="/js/controllers/dashboardCtrl.js"></script>

+ 2 - 1
front/src/views/dashboard.html

@@ -35,7 +35,8 @@
                         </div>
                         </div>
                         <div class="label">{{rule.policy.label}}</div>
                         <div class="label">{{rule.policy.label}}</div>
                         <div class="result">
                         <div class="result">
-                            {{rule.value}}
+                            <span ng-if="rule.policy.unit == 'bytes'">{{rule.value | bytes}}</span>
+                            <span ng-if="rule.policy.unit != 'bytes'">{{rule.value}}</span>
                             <span ng-if="rule.abnormal" class="icon-warning"></span>
                             <span ng-if="rule.abnormal" class="icon-warning"></span>
                             <span ng-if="rule.abnormalityScore <= -100" class="icon-warning"></span>
                             <span ng-if="rule.abnormalityScore <= -100" class="icon-warning"></span>
                             <span ng-if="rule.abnormalityScore <= -300" class="icon-warning"></span>
                             <span ng-if="rule.abnormalityScore <= -300" class="icon-warning"></span>

+ 21 - 2
front/src/views/rule.html

@@ -9,7 +9,11 @@
             <div>{{rule.score}}/100</div>
             <div>{{rule.score}}/100</div>
         </div>
         </div>
         <div class="right">
         <div class="right">
-            <h3>Value: {{rule.value}}</h3>
+            <h3>
+                Value:
+                <span ng-if="rule.policy.unit == 'bytes'">{{rule.value | bytes}}</span>
+                <span ng-if="rule.policy.unit != 'bytes'">{{rule.value}}</span>
+            </h3>
             <div ng-bind-html="rule.policy.message" class="message"></div>
             <div ng-bind-html="rule.policy.message" class="message"></div>
         </div>
         </div>
     </div>
     </div>
@@ -165,7 +169,6 @@
             </div>
             </div>
         </div>
         </div>
 
 
-
         <div ng-if="!rule.offendersObj.list" class="offendersHtml">
         <div ng-if="!rule.offendersObj.list" class="offendersHtml">
             
             
             <div ng-if="policyName === 'DOMelementMaxDepth'">
             <div ng-if="policyName === 'DOMelementMaxDepth'">
@@ -194,6 +197,22 @@
         </div>
         </div>
     </div>
     </div>
 
 
+    <div ng-if="policyName === 'totalWeight'">
+        <h3>Weight by MIME type</h3>
+        <div class="totalWeightPie">
+            <canvas class="chart chart-doughnut" data="weightData" labels="weightLabels" options="weightOptions" colours="weightColours" legend="true"></canvas>
+        </div>
+        <div ng-repeat="type in weightLabels">
+            <h3>{{rule.offendersObj.list.byType[type].totalWeight | bytes}} of {{type}}</h3>
+            <div class="offendersTable">
+                <div ng-repeat="request in rule.offendersObj.list.byType[type].requests | orderBy:'-weight'" ng-if="request.weight > 0">
+                    <div><url-link url="request.url" max-length="60"></url-link></div>
+                    <div ng-class="{hugeFile: request.weight > 102400}">{{request.weight | bytes}}</div>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <div ng-if="policyName === 'DOMaccesses'">
     <div ng-if="policyName === 'DOMaccesses'">
         <h3>{{rule.value}} offenders</h3>
         <h3>{{rule.value}} offenders</h3>
         Please open the <a href="/result/{{runId}}/timeline">JS timeline</a>
         Please open the <a href="/result/{{runId}}/timeline">JS timeline</a>

+ 10 - 0
lib/metadata/policies.js

@@ -852,6 +852,16 @@ var policies = {
             };
             };
         }
         }
     },
     },
+    "totalWeight": {
+        "tool": "weightChecker",
+        "label": "Total weight",
+        "message": "<p>The weight is of course very important if you want the page to load fast. Try to stay under 1MB, which is alreay very long to download over a slow connection.</p>",
+        "isOkThreshold": 716800,
+        "isBadThreshold": 2097152,
+        "isAbnormalThreshold": 3145728,
+        "hasOffenders": true,
+        "unit": 'bytes'
+    },
     "requests": {
     "requests": {
         "tool": "phantomas",
         "tool": "phantomas",
         "label": "Total requests number",
         "label": "Total requests number",

+ 17 - 27
lib/metadata/scoreProfileGeneric.json

@@ -3,7 +3,7 @@
         "domComplexity": {
         "domComplexity": {
             "label": "DOM complexity",
             "label": "DOM complexity",
             "policies": {
             "policies": {
-                "DOMelementsCount": 1,
+                "DOMelementsCount": 3,
                 "DOMelementMaxDepth": 1,
                 "DOMelementMaxDepth": 1,
                 "iframesCount": 1,
                 "iframesCount": 1,
                 "DOMidDuplicated": 1
                 "DOMidDuplicated": 1
@@ -69,44 +69,34 @@
                 "cssRedundantChildNodesSelectors": 1
                 "cssRedundantChildNodesSelectors": 1
             }
             }
         },
         },
-        "requests": {
-            "label": "Requests number",
+        "pageWeight": {
+            "label": "Page weight",
             "policies": {
             "policies": {
-                "requests": 5,
-                "htmlCount": 0,
-                "jsCount": 1,
-                "cssCount": 1,
-                "imageCount": 0,
-                "webfontCount": 2,
-                "videoCount": 0,
-                "jsonCount": 0,
-                "otherCount": 0
+                "totalWeight": 5
             }
             }
         },
         },
-        "smallRequests": {
-            "label": "Small requests",
+        "requests": {
+            "label": "Requests",
             "policies": {
             "policies": {
-                "smallJsFiles": 1,
-                "smallCssFiles": 1,
-                "smallImages": 1
+                "requests": 5,
+                "domains": 3,
+                "notFound": 3,
+                "multipleRequests": 2,
+                "smallRequests": 1
             }
             }
         },
         },
-        "network": {
-            "label": "Network",
+        "serverConfig": {
+            "label": "Server config",
             "policies": {
             "policies": {
-                "notFound": 2,
-                "assetsNotGzipped": 1.5,
                 "closedConnections": 2,
                 "closedConnections": 2,
-                "multipleRequests": 2,
                 "cachingNotSpecified": 1,
                 "cachingNotSpecified": 1,
                 "cachingDisabled": 1,
                 "cachingDisabled": 1,
-                "cachingTooShort": 1,
-                "domains": 1
+                "cachingTooShort": 1
             }
             }
         }
         }
     },
     },
     "globalScore": {
     "globalScore": {
-        "domComplexity": 1,
+        "domComplexity": 2,
         "domManipulations": 2,
         "domManipulations": 2,
         "scroll": 1,
         "scroll": 1,
         "badJavascript": 1,
         "badJavascript": 1,
@@ -114,8 +104,8 @@
         "cssSyntaxError": 1,
         "cssSyntaxError": 1,
         "cssComplexity": 1,
         "cssComplexity": 1,
         "badCSS": 1,
         "badCSS": 1,
+        "pageWeight": 3,
         "requests": 3,
         "requests": 3,
-        "smallRequests": 1,
-        "network": 2
+        "serverConfig": 1
     }
     }
 }
 }

+ 1 - 1
lib/tools/weightChecker.js

@@ -102,7 +102,7 @@ var WeightChecker = function() {
         };
         };
 
 
         requests.forEach(function(req) {
         requests.forEach(function(req) {
-            var weight = (typeof req.weightCheck.bodySize === 'number') ? req.weightCheck.bodySize + req.weightCheck.headersSize : req.contentLength;
+            var weight = ((typeof req.weightCheck.bodySize === 'number') ? req.weightCheck.bodySize + req.weightCheck.headersSize : req.contentLength) || 0;
             var type = req.type || 'other';
             var type = req.type || 'other';
 
 
             results.totalWeight += weight;
             results.totalWeight += weight;