Ver Fonte

Add offenders to imageOptimization

Gaël Métais há 10 anos atrás
pai
commit
9ccca3b33b

+ 24 - 4
front/src/css/rule.css

@@ -164,16 +164,18 @@
   font-style: italic;
   font-weight: normal;
 }
-.colorPalette {
-  width: 30em;
-  border: 2px solid #000;
-  text-align: left;
+.checker {
   /* Checkerboard background */
   background-color: #ddd;
   background-image: linear-gradient(45deg, #aaaaaa 25%, transparent 25%, transparent 75%, #aaaaaa 75%, #aaaaaa), linear-gradient(45deg, #aaaaaa 25%, transparent 25%, transparent 75%, #aaaaaa 75%, #aaaaaa);
   background-size: 1em 1em;
   background-position: 0 0, 0.5em 0.5em;
 }
+.colorPalette {
+  width: 30em;
+  border: 2px solid #000;
+  text-align: left;
+}
 .colorPalette > div {
   display: inline-block;
   height: 2em;
@@ -216,3 +218,21 @@
   font-weight: bold;
   color: #e74c3c;
 }
+.imageOffenders {
+  display: table;
+  border-spacing: 3em;
+  width: 90%;
+}
+.imageOffenders > div {
+  display: table-row;
+}
+.imageOffenders > div > div {
+  display: table-cell;
+  vertical-align: middle;
+}
+.imageOffenders img {
+  max-height: 10em;
+  max-width: 40em;
+  border: 1px solid #000;
+  margin-top: 0.5em;
+}

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

@@ -864,6 +864,10 @@
             
             var kilo = bytes / 1024;
 
+            if (kilo < 1) {
+                return bytes + ' Bytes';
+            }
+
             if (kilo < 100) {
                 return kilo.toFixed(1) + ' KB';
             }

+ 29 - 5
front/src/less/rule.less

@@ -176,16 +176,18 @@
     }
 }
 
-.colorPalette {
-    width: 30em;
-    border: 2px solid #000;
-    text-align: left;
-
+.checker {
     /* Checkerboard background */
     background-color: #ddd;
     background-image: linear-gradient(45deg, #AAA 25%, transparent 25%, transparent 75%, #AAA 75%, #AAA), linear-gradient(45deg, #AAA 25%, transparent 25%, transparent 75%, #AAA 75%, #AAA);
     background-size:1em 1em;
     background-position:0 0, 0.5em 0.5em;
+}
+
+.colorPalette {
+    width: 30em;
+    border: 2px solid #000;
+    text-align: left;
 
     > div {
         display: inline-block;
@@ -235,4 +237,26 @@
 .hugeFile {
     font-weight: bold;
     color: #e74c3c;
+}
+
+.imageOffenders {
+    display: table;
+    border-spacing: 3em;
+    width: 90%;
+
+    > div {
+        display: table-row;
+
+        > div {
+            display: table-cell;
+            vertical-align: middle;
+        }
+    }
+
+    img {
+        max-height: 10em;
+        max-width: 40em;
+        border: 1px solid #000;
+        margin-top: 0.5em;
+    }
 }

+ 18 - 1
front/src/views/rule.html

@@ -190,7 +190,7 @@
 
             <div ng-if="policyName === 'cssColors' && rule.offendersObj.count > 0">
                 <p>This is the colors palette, sized by total occurrences:</p>
-                <div class="colorPalette">
+                <div class="colorPalette checker">
                     <div ng-repeat="offender in rule.offendersObj.palette" style="background-color: {{offender.color}}; width: {{offender.occurrences * 100 / rule.offendersObj.palette[0].occurrences}}%"><div>{{offender.color}} ({{offender.occurrences}} times)</div></div>
                 </div>
             </div>
@@ -213,6 +213,23 @@
         </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">
+            <div ng-repeat="image in rule.offendersObj.list.images | orderBy:'-gain'">
+                <div>
+                    Current file: <url-link url="image.url" max-length="50"></url-link>
+                    <div><a href="{{image.url}}" target="_blank"><img ng-src="{{image.url}}" class="checker" /></a></div>
+                </div>
+                <div>
+                    <p>Current weight: {{image.original | bytes}}</p>
+                    <p ng-if="image.lossless">With a lossless optimization:<br/>{{image.lossless | bytes}} (<b>-{{image.original - image.lossless | bytes}}</b>)</p>
+                    <p ng-if="image.lossy">With a lossy optimization:<br/>{{image.lossy | bytes}} (<b>-{{image.original - image.lossy | bytes}}</b>)</p>
+                </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>

+ 1 - 1
lib/metadata/policies.js

@@ -865,7 +865,7 @@ var policies = {
     "imageOptimization": {
         "tool": "weightChecker",
         "label": "Image optimization",
-        "message": "<p>This metric mesures the number of bytes that could be saved by optimizing images.</p><p>Image optimization is generally one of the easiest way to reduce a page weight, and as a result, the page load time. Don't use Photoshop or other image editing tools, they lie to you because they're generally not very good for optimization. Use specialized tools such as <a href=\"https://kraken.io/\" target=\"_blank\">Kraken.io</a> or the excellent <a href=\"https://imageoptim.com/\" target=\"_blank\">ImageOption</a> on Mac.</p><p>The tools in use in YellowLabTools are not set to their maximum optimization power, so you might be able to compress even more (the max JPEG quality is set to 85, which should be sufficient for any website).</p>",
+        "message": "<p>This metric mesures the number of bytes that could be saved by optimizing images.</p><p>Image optimization is generally one of the easiest way to reduce a page weight, and as a result, the page load time. Don't use Photoshop or other image editing tools, they're not very good for optimization. Use specialized tools such as <a href=\"https://kraken.io/\" target=\"_blank\">Kraken.io</a> or the excellent <a href=\"https://imageoptim.com/\" target=\"_blank\">ImageOption</a> on Mac. For SVG images, you can use <a href=\"https://jakearchibald.github.io/svgomg/\" target=\"_blank\">SVGOMG</a></p><p>The tools in use in YellowLabTools are not set to their maximum optimization power, so you might be able to compress even more.</p>",
         "isOkThreshold": 30720,
         "isBadThreshold": 122880,
         "isAbnormalThreshold": 204800,

+ 3 - 1
lib/tools/weightChecker/imageOptimizer.js

@@ -149,10 +149,12 @@ var ImageOptimizer = function() {
         return deferred.promise;
     }
 
+    // The gain is estimated of enough value if it's over 2KB or over 20%,
+    // but it's ignored if is below 100 bytes
     function gainIsEnough(oldWeight, newWeight) {
         var gain = oldWeight - newWeight;
         var ratio = gain / oldWeight;
-        return (gain > 2048 || ratio > 0.2);
+        return (gain > 2048 || (ratio > 0.2 && gain > 100));
     }
 
     function isJpeg(entry) {

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

@@ -140,45 +140,16 @@ var WeightChecker = function() {
     function listImageNotOptimized(requests) {
         var results = {
             totalGain: 0,
-            byType: {
-                jpeg: {
-                    totalGain: 0,
-                    requests: []
-                },
-                png: {
-                    totalGain: 0,
-                    requests: []
-                },
-                svg: {
-                    totalGain: 0,
-                    requests: []
-                }
-            }
+            images: []
         };
 
         requests.forEach(function(req) {
-            var type = null;
-
-            switch(req.contentType) {
-                case 'image/jpeg':
-                    type = 'jpeg';
-                    break;
-                case 'image/png':
-                    type = 'png';
-                    break;
-                case 'image/svg+xml':
-                    type = 'svg';
-                    break;
-            }
-
-            if (type && req.weightCheck.bodySize && req.weightCheck.isOptimized === false) {
+            if (req.weightCheck.bodySize && req.weightCheck.isOptimized === false) {
                 var gain = req.weightCheck.bodySize - req.weightCheck.optimized;
 
                 results.totalGain += gain;
 
-                results.byType[type].totalGain += gain;
-
-                results.byType[type].requests.push({
+                results.images.push({
                     url: req.url,
                     original: req.weightCheck.bodySize,
                     optimized: req.weightCheck.optimized,

+ 2 - 1
test/core/imageOptimizerTest.js

@@ -309,7 +309,8 @@ describe('imageOptimizer', function() {
         imageOptimizer.gainIsEnough(20000, 21000).should.equal(false);
         imageOptimizer.gainIsEnough(20000, 40000).should.equal(false);
         imageOptimizer.gainIsEnough(20000, 19500).should.equal(false);
-        imageOptimizer.gainIsEnough(200, 100).should.equal(true);
+        imageOptimizer.gainIsEnough(250, 120).should.equal(true);
+        imageOptimizer.gainIsEnough(200, 120).should.equal(false);
         imageOptimizer.gainIsEnough(2000, 1900).should.equal(false);
         imageOptimizer.gainIsEnough(200000, 197000).should.equal(true);
     });

+ 1 - 2
test/core/weightCheckerTest.js

@@ -87,8 +87,7 @@ describe('weightChecker', function() {
 
             data.toolsResults.weightChecker.offenders.should.have.a.property('imageOptimization');
             data.toolsResults.weightChecker.offenders.imageOptimization.totalGain.should.be.above(0);
-            data.toolsResults.weightChecker.offenders.imageOptimization.byType.jpeg.requests.length.should.equal(1);
-            data.toolsResults.weightChecker.offenders.imageOptimization.byType.svg.requests.length.should.equal(1);
+            data.toolsResults.weightChecker.offenders.imageOptimization.images.length.should.equal(2);
 
             done();
         })