Detect non WOFF2 fonts and estimate gain

This commit is contained in:
Gaël Métais
2020-12-21 01:18:56 +01:00
parent dd0c17a9d4
commit d93af3d6e4
7 changed files with 170 additions and 13 deletions
+20
View File
@@ -483,6 +483,26 @@
</div>
</div>
<div ng-if="policyName === 'nonWoff2Fonts'">
<h3 ng-if="rule.value > 0">{{rule.value | bytes}} could be saved on <ng-pluralize count="rule.offendersObj.list.fonts.length" when="{'one': '1 file', 'other': '{} files'}"></ng-pluralize></h3>
<div class="table">
<div class="headers">
<div>File</div>
<div>Current weight</div>
<div>Woff 2 weight</div>
<div>Gain</div>
</div>
<div ng-repeat="file in rule.offendersObj.list.fonts | orderBy:'-gain'">
<div>
<url-link url="file.url" max-length="70"></url-link>
</div>
<div>{{file.originalSize | bytes}}</div>
<div>{{file.woff2Size | bytes}}</div>
<div><b>-{{file.gain | bytes}}</b></div>
</div>
</div>
</div>
<div ng-if="policyName === 'http2'">
<h3>Protocols advertised by the server</h3>
<div class="offendersTable">
+10
View File
@@ -927,6 +927,16 @@ var policies = {
return offenders;
}
},*/
"nonWoff2Fonts": {
"tool": "redownload",
"label": "Woff 2",
"message": "<p>The fonts listed here could be lighter if they were served with the latest woff 2 font file format. Some online tools can help you easily convert older formats to woff 2.</p>",
"isOkThreshold": 0,
"isBadThreshold": 61440,
"isAbnormalThreshold": 122880,
"hasOffenders": true,
"unit": 'bytes'
},
"oldHttpProtocol": {
"label": "HTTP/1 requests",
"message": "<p>HTTP/2 is the latest version of the HTTP protocol. It is designed to optimize load speed. HTTP/3 will come soon and should be even faster!</p><p>When a domain sends more than 4 requests over HTTP/1, this metric counts one point for each new request. Below 5 requests, the benefits of HTTP/2 are generally less significant.</p>",
+3 -1
View File
@@ -87,7 +87,9 @@
"label": "Web fonts",
"policies": {
"fontsCount": 1,
"heavyFonts": 1
"heavyFonts": 0.5,
//"unusedUnicodeRanges": 0.5,
"nonWoff2Fonts": 0.5
}
},
"serverConfig": {
+12 -6
View File
@@ -15,9 +15,6 @@ var ContentTypeChecker = function() {
function checkContentType(entry) {
var deferred = Q.defer();
debug('Entering contentTypeChecker');
debug(entry);
// Setting isSomething values:
switch(entry.type) {
@@ -59,9 +56,15 @@ var ContentTypeChecker = function() {
try {
foundType = findContentType(entry.weightCheck.bodyBuffer);
if (foundType !== null && foundType.type !== entry.type) {
debug('Content type %s is wrong for %s. It should be %s.', entry.type, entry.ulr, foundType.type);
rewriteContentType(entry, foundType);
if (foundType !== null) {
if (foundType.type === 'webfont') {
// Always rewrite fonts for woff2 checking
rewriteContentType(entry, foundType);
} else if (foundType.type !== entry.type) {
// For other kind of files, just rewrite if needed
debug('Content type %s is wrong for %s. It should be %s.', entry.type, entry.ulr, foundType.type);
rewriteContentType(entry, foundType);
}
}
} catch(err) {
@@ -188,6 +191,7 @@ var ContentTypeChecker = function() {
updateFn: function(entry) {
entry.type = 'webfont';
entry.isWebFont = true;
entry.isWoff = true;
}
},
woff2: {
@@ -196,6 +200,7 @@ var ContentTypeChecker = function() {
updateFn: function(entry) {
entry.type = 'webfont';
entry.isWebFont = true;
entry.isWoff2 = true;
}
},
otf: {
@@ -212,6 +217,7 @@ var ContentTypeChecker = function() {
updateFn: function(entry) {
entry.type = 'webfont';
entry.isWebFont = true;
entry.isTTF = true;
}
},
eot: {
+82 -5
View File
@@ -2,6 +2,8 @@ var debug = require('debug')('ylt:fontAnalyzer');
var Q = require('q');
var fontkit = require('fontkit');
var woffTools = require('woff-tools');
var ttf2woff2 = require('ttf2woff2');
var FontAnalyzer = function() {
@@ -19,25 +21,100 @@ var FontAnalyzer = function() {
if (entry.isWebFont) {
debug('File %s is a font. Let\'s have a look inside!', entry.url);
getMetricsFromFont(entry, charsListOnPage)
convertToWoff2(entry)
.then(function(entry) {
return getMetricsFromFont(entry, charsListOnPage);
})
.then(function(fontMetrics) {
entry.fontMetrics = fontMetrics;
deferred.resolve(entry);
})
.fail(function(error) {
debug('Could not open the font: %s', error);
deferred.resolve(entry);
});
} else {
deferred.resolve(entry);
}
deferred.resolve(entry);
return deferred.promise;
}
function convertToWoff2(entry) {
var deferred = Q.defer();
debug('Entering font format converter...');
if (entry.isWoff2) {
debug('File is already a woff2.');
deferred.resolve(entry);
} else if (entry.isWoff) {
debug('File is a woff. Let\'s convert to woff2');
try {
var fileSize = entry.weightCheck.bodySize;
debug('Current file size is %d', fileSize);
var ttf = woffTools.toSfnt(entry.weightCheck.bodyBuffer);
var woff2 = ttf2woff2(ttf);
var newFileSize = woff2.length;
debug('New image size is %d', newFileSize);
debug('Filesize is %d bytes smaller (-%d%)', fileSize - newFileSize, Math.round((fileSize - newFileSize) * 100 / fileSize));
entry.weightCheck.sizeAsWoff2 = newFileSize;
deferred.resolve(entry);
} catch(error) {
deferred.reject(error);
}
} else if (entry.isTtf) {
debug('File is a TTF. Let\'s convert to woff2');
try {
var fileSize = entry.weightCheck.bodySize;
debug('Current file size is %d', fileSize);
var woff2 = ttf2woff2(entry.weightCheck.bodyBuffer);
var newFileSize = woff2.length;
debug('New image size is %d', newFileSize);
debug('Filesize is %d bytes smaller (-%d%)', fileSize - newFileSize, Math.round((fileSize - newFileSize) * 100 / fileSize));
entry.weightCheck.sizeAsWoff2 = newFileSize;
deferred.resolve(entry);
} catch(error) {
deferred.reject(error);
}
} else {
// Other font formats are not handled
deferred.resolve(entry);
}
return deferred.promise;
}
// The gain is estimated of enough value if it's over 1KB 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 && gain > 100));
}
function getMetricsFromFont(entry, charsListOnPage) {
var deferred = Q.defer();
+40
View File
@@ -167,6 +167,10 @@ var Redownload = function() {
offenders.fontsCount = listFonts(results);
metrics.fontsCount = offenders.fontsCount.count;
// Conversion to woff2
offenders.nonWoff2Fonts = listNonWoff2Fonts(results);
metrics.nonWoff2Fonts = offenders.nonWoff2Fonts.totalGain;
// Heavy fonts
offenders.heavyFonts = listHeavyFonts(results);
metrics.heavyFonts = offenders.heavyFonts.totalGain;
@@ -551,6 +555,42 @@ var Redownload = function() {
};
}
function listNonWoff2Fonts(requests) {
var results = {
totalGain: 0,
fonts: []
};
requests.forEach(function(req) {
if (!req.isWoff2 && req.weightCheck.sizeAsWoff2) {
var before = req.weightCheck.bodySize;
var after = req.weightCheck.sizeAsWoff2;
var gain = before - after;
var type = null;
if (req.isWoff) {
type = 'woff';
} else if (req.isTtf) {
type = 'ttf';
}
if (gain > 200) {
results.totalGain += gain;
results.fonts.push({
url: req.url,
originalSize: before,
type: type,
woff2Size: after,
gain: gain
});
}
}
});
return results;
}
function listHeavyFonts(requests) {
var list = [];
var totalGain = 0;
+3 -1
View File
@@ -67,7 +67,9 @@
"request": "2.88.0",
"rimraf": "2.6.3",
"temporary": "0.0.8",
"uglify-js": "3.4.9"
"ttf2woff2": "3.0.0",
"uglify-js": "3.4.9",
"woff-tools": "0.1.0"
},
"devDependencies": {
"chai": "~4.2.0",