Skip to content

Instantly share code, notes, and snippets.

@kanavarora
Last active June 7, 2019 08:24
Show Gist options
  • Save kanavarora/cc767dd2918fbcef3d6ce2357674aced to your computer and use it in GitHub Desktop.
Save kanavarora/cc767dd2918fbcef3d6ce2357674aced to your computer and use it in GitHub Desktop.
Simple utility to track your bundle/chunk sizes with each release
/*
Utility to analyze bundle chunks over versions.
Assumes: webpack has already created the bundle summary json file -> stats.json
Parameters:
version: (Optional) a string that labels the current bundle with the version
provided and saves the summary in a csv file.
Output:
If run the first time, generates a csv file bundleAnalaysis.csv, which
tracks bundle sizes by version. Adds one row with the current analysis.
If run the next time, analyzes the current stats.json with the last row
in bundleAnalysis.csv and prints out summary to command line.
If run with version, does the same as above plus adds a row with the version
in bundleAnalysis.csv. This will be used as the next baseline.
Usage:
In package.json, add this script:
"prod-bundle-analyze": "webpack --config webpack/prod.config.js --json > stats.json && node bundleAnalyzer.js"
Run script first time to create a baseline.
npm run prod-bundle-analyze
If you want to analyze your current code (will compare with the last baseline)
npm run prod-bundle-analyze
If you want to create a new baseline (use this when you have a new release)
npm run prod-bundle-analyze v2.0
*/
const csv = require('csvtojson');
var path = require('path');
var json2csv = require('json2csv');
const jsonBundleFilePath = 'stats.json';
var fs = require('fs');
var obj = JSON.parse(fs.readFileSync(jsonBundleFilePath, 'utf8'));
var args = process.argv.slice(2);
var versionName = null;
if (args[0]) {
versionName = args[0];
}
var assetsByChunkName = obj.assetsByChunkName;
var assets = obj.assets;
var summarySize = {};
for (var i = 0; i < assets.length; i++) {
var asset = assets[i];
if (!asset.chunkNames || asset.chunkNames.length != 1) {
continue;
}
var chunkName = asset.chunkNames[0];
if (!assetsByChunkName[chunkName]) {
continue;
}
var assetName = asset.name;
var assetSize = asset.size;
var extension = path.extname(assetName);
// flat keys doesnt work of csv to json. this is sad, so have to remove the dot.
summarySize[chunkName + " " + extension.substring(1)] = parseInt(assetSize)/1000.0;
}
const summaryFileName = 'build_tools/bundleAnalysis.csv';
const summaryFileNameBackup = 'build_tools/bundleAnalysis_backup.csv';
if (fs.existsSync(summaryFileName)) {
analyzeNewBundle(summarySize);
} else {
writeCSVFirstTime(summarySize);
}
function analyzeNewBundle(summarySize) {
const csvFilePath=summaryFileName;
var csvString = fs.readFileSync(csvFilePath, "utf8");
var jsonObjects = [];
csv({flatKeys:true})
.fromString(csvString)
.on('json',(jsonObj)=>{
jsonObjects.push(jsonObj);
var lastBundleSummary = jsonObjects[jsonObjects.length-1];
for (var assetName in summarySize) {
if (summarySize.hasOwnProperty(assetName)) {
// do stuff
var oldSize = lastBundleSummary[assetName];
var newSize = summarySize[assetName];
var changeInSize = newSize - oldSize;
var stringToPrint = assetName + ':' + oldSize + 'kB->' + newSize + 'kB = ';
if (oldSize == 0) {
stringToPrint += 'new file';
} else {
stringToPrint += (changeInSize*100.0/oldSize) + '% increase';
}
console.log(stringToPrint);
}
}
})
.on('done',(error)=>{
//console.log(jsonObjects);
if (versionName) {
saveResultInCSV(jsonObjects, summarySize, versionName);
}
})
}
function saveResultInCSV(oldBundleJsonObjects, summarySize, versionName) {
// copy to backup
fs.createReadStream(summaryFileName).pipe(fs.createWriteStream(summaryFileNameBackup));
summarySize['version'] = versionName;
summarySize['date'] = (new Date()).toDateString();
oldBundleJsonObjects.push(summarySize);
var fieldsDict = {};
for (var i = 0; i < oldBundleJsonObjects.length; i++) {
var bundleJsonObj = oldBundleJsonObjects[i];
for (var fieldName in bundleJsonObj) {
if (bundleJsonObj.hasOwnProperty(fieldName) && !fieldsDict.hasOwnProperty[fieldName]) {
fieldsDict[fieldName] = true;
}
}
}
var csv = json2csv({ data: oldBundleJsonObjects, fields: Object.keys(fieldsDict)});
fs.writeFile(summaryFileName, csv, function(err) {
if (err) throw err;
console.log('summary file created');
});
}
function writeCSVFirstTime (summarySize) {
var currentTime = new Date();
var fields = ['version', 'date'];
fields = fields.concat(Object.keys(summarySize));
summarySize.version = '0.0';
summarySize.date = currentTime.toDateString();
var csv = json2csv({ data: summarySize, fields: fields });
fs.writeFile(summaryFileName, csv, function(err) {
if (err) throw err;
console.log('file saved');
});
}
@whilelucky
Copy link

whilelucky commented Mar 13, 2017

Just checking in to see if there's an npm module available for this now? or is this still the best available version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment