-
-
Save chrisabrams/cd77ee4e93fc54d243e4194e560dd706 to your computer and use it in GitHub Desktop.
Simple utility to track your bundle/chunk sizes with each release
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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'); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment