瀏覽代碼

Replace TotalRequests and SmallRequests rules

Gaël Métais 10 年之前
父節點
當前提交
ccbb324270

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

@@ -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;
+}

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

@@ -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;
 }

+ 38 - 0
front/src/views/rule.html

@@ -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
lib/metadata/policies.js

@@ -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;
-                    })
-            };
-        }
-    },
-    "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);
-                    })
-            };
-        }
+        "isAbnormalThreshold": 180,
+        "hasOffenders": true
     },
-    "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",

+ 1 - 1
lib/metadata/scoreProfileGeneric.json

@@ -81,7 +81,7 @@
         "requests": {
             "label": "Requests",
             "policies": {
-                "requests": 5,
+                "totalRequests": 5,
                 "domains": 3,
                 "notFound": 3,
                 "multipleRequests": 2,

+ 62 - 3
lib/tools/weightChecker/weightChecker.js

@@ -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();

+ 17 - 0
test/core/weightCheckerTest.js

@@ -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();
         })