webpack-bundle-size-analyzer
Version:
A utility to find how your dependencies are contributing to the size of your Webpack bundles
144 lines (143 loc) • 5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
var filesize = require("filesize");
var path = require("path");
var webpack_stats = require("./webpack_stats");
function modulePath(identifier) {
// the format of module paths is
// '(<loader expression>!)?/path/to/module.js'
var loaderRegex = /.*!/;
return identifier.replace(loaderRegex, '');
}
/** Walk a dependency size tree produced by dependencySizeTree() and output the
* size contributed to the bundle by each package's own code plus those
* of its dependencies.
*/
function printDependencySizeTree(node, shareStats, depth, outputFn) {
if (depth === void 0) { depth = 0; }
if (outputFn === void 0) { outputFn = console.log; }
if (node.hasOwnProperty('bundleName')) {
var rootNode = node;
outputFn("Bundle: " + rootNode.bundleName);
}
var childrenBySize = node.children.sort(function (a, b) {
return b.size - a.size;
});
var totalSize = node.size;
var remainder = totalSize;
var includedCount = 0;
var prefix = '';
for (var i = 0; i < depth; i++) {
prefix += ' ';
}
for (var _i = 0, childrenBySize_1 = childrenBySize; _i < childrenBySize_1.length; _i++) {
var child = childrenBySize_1[_i];
++includedCount;
var out = "" + prefix + child.packageName + ": " + filesize(child.size);
if (shareStats) {
var percentage = ((child.size / totalSize) * 100).toPrecision(3);
out = out + " (" + percentage + "%)";
}
outputFn(out);
printDependencySizeTree(child, shareStats, depth + 1, outputFn);
remainder -= child.size;
if (remainder < 0.01 * totalSize) {
break;
}
}
if (depth === 0 || remainder !== totalSize) {
var out = prefix + "<self>: " + filesize(remainder);
if (shareStats) {
var percentage = ((remainder / totalSize) * 100).toPrecision(3);
out = out + " (" + percentage + "%)";
}
outputFn(out);
}
}
exports.printDependencySizeTree = printDependencySizeTree;
function bundleSizeTree(stats) {
var statsTree = {
packageName: '<root>',
size: 0,
children: []
};
if (stats.name) {
statsTree.bundleName = stats.name;
}
// extract source path for each module
var modules = stats.modules.map(function (mod) {
return {
path: modulePath(mod.identifier),
size: mod.size
};
});
modules.sort(function (a, b) {
if (a === b) {
return 0;
}
else {
return a < b ? -1 : 1;
}
});
modules.forEach(function (mod) {
// convert each module path into an array of package names, followed
// by the trailing path within the last module:
//
// root/node_modules/parent/node_modules/child/file/path.js =>
// ['root', 'parent', 'child', 'file/path.js'
var packages = mod.path.split(new RegExp('\\' + path.sep + 'node_modules\\' + path.sep));
var filename = '';
if (packages.length > 1) {
var lastSegment = packages.pop();
var lastPackageName = '';
if (lastSegment[0] === ('@')) {
// package is a scoped package
var offset = lastSegment.indexOf(path.sep) + 1;
lastPackageName = lastSegment.slice(0, offset + lastSegment.slice(offset).indexOf(path.sep));
}
else {
lastPackageName = lastSegment.slice(0, lastSegment.indexOf(path.sep));
}
packages.push(lastPackageName);
filename = lastSegment.slice(lastPackageName.length + 1);
}
else {
filename = packages[0];
}
packages.shift();
var parent = statsTree;
parent.size += mod.size;
packages.forEach(function (pkg) {
var existing = parent.children.filter(function (child) { return child.packageName === pkg; });
if (existing.length > 0) {
existing[0].size += mod.size;
parent = existing[0];
}
else {
var newChild = {
packageName: pkg,
size: mod.size,
children: []
};
parent.children.push(newChild);
parent = newChild;
}
});
});
return statsTree;
}
/** Takes the output of 'webpack --json', and returns
* an array of trees of require()'d package names and sizes.
*
* There is one entry in the array for each bundle specified
* in the Webpack compilation.
*/
function dependencySizeTree(stats) {
if (webpack_stats.isMultiCompilation(stats)) {
return stats.children.map(bundleSizeTree);
}
else {
return [bundleSizeTree(stats)];
}
}
exports.dependencySizeTree = dependencySizeTree;
;