Files
workbox/gulp-tasks/utils/analyse-properties.js
T
Jeffrey PosnickandGitHub 9d88f2abae The contents of v3, reconciled with master (#1357)
* The contents of v3, reconciled with master.

* Remove a few stray files.

* Another extra file.

* Two more deletions.

* Setting up for stable release

* v3.0.0

* Updating CDN and versions

* Doc repair for wf (#1358)

* Changing doc structure to work with WF

* Changing doc structure to work with WF
2018-03-13 15:20:33 -04:00

113 lines
3.3 KiB
JavaScript

/*
* This file should be run as a node script to analyse the content of the
* browser bundles.
*
* It's an extremely naive approach to picking property names out and seeing
* how often they are used in the final browser bundles. This can be
* used to detect variable names that are long and used repeatedly meaning
* that a small refactor allowing `uglify-es` to mangle these properties,
* could lead to reasonable improvement in final bundle size.
*
* This is very rough and vague. It needs to be run manually and if it's not
* used can and should be removed from Workbox repo.
*/
const glob = require('glob');
const path = require('path');
const fs = require('fs-extra');
const babylon = require('babylon');
const constants = require('./constants');
const logHelper = require('../../infra/utils/log-helper');
class AnalyseBuildForProperties {
run() {
const filePaths = this.getBuildFiles();
return Promise.all(filePaths.map((filePath) => {
const rawAnalysis = this.analyzeFile(filePath);
const analysis = this.tidyData(rawAnalysis);
return {
filePath,
analysis,
};
}));
}
getBuildFiles() {
// workbox-sw doesn't include .prod. in the build name.
const buildGlob = path.join(__dirname, '..', '..', 'packages',
'*', constants.PACKAGE_BUILD_DIRNAME, '{*.prod.js,workbox-sw.js}');
return glob.sync(buildGlob);
}
analyzeFile(filePath) {
const fileContents = fs.readFileSync(filePath).toString();
const parsedCode = babylon.parse(fileContents);
const tokens = parsedCode.tokens;
const nameTokens = tokens.filter((token) => {
return token.type.label === 'name';
});
const matches = {};
nameTokens.forEach((token) => {
const variableName = token.value;
if (!matches[variableName]) {
matches[variableName] = 0;
}
matches[variableName]++;
});
return Object.keys(matches).map((matchKey) => {
return {
propertyName: matchKey,
propertyCount: matches[matchKey],
};
});
}
tidyData(analysisEntries) {
return analysisEntries.filter((entry) => {
// If there is only one entry or it's a single character it's
// either not important or it's already been minified.
return entry.propertyCount > 1 && entry.propertyName.length > 1;
})
.filter((entry) => {
switch (entry.propertyName) {
case 'await':
case 'async':
return false;
default:
return true;
}
})
.sort((a, b) => {
return b.propertyCount - a.propertyCount;
});
}
printDetails({filePath, analysis}) {
let longestPropertyName = 0;
analysis.forEach((entry) => {
if (entry.propertyName.length > longestPropertyName) {
longestPropertyName = entry.propertyName.length;
}
});
logHelper.log();
logHelper.log(`Results for '${path.relative(process.cwd(), filePath)}'`);
logHelper.log();
analysis.forEach((entry) => {
const numberOfSpaces = longestPropertyName - entry.propertyName.length;
const extraSpace = ' '.repeat(numberOfSpaces);
logHelper.log(` ${entry.propertyName} ` +
`${extraSpace} ${entry.propertyCount}`);
});
logHelper.log();
}
}
module.exports = AnalyseBuildForProperties;