Skip to content

Instantly share code, notes, and snippets.

@BenoitZugmeyer
Last active March 7, 2016 13:04
Show Gist options
  • Save BenoitZugmeyer/b0b46bae7f9308a68af4 to your computer and use it in GitHub Desktop.
Save BenoitZugmeyer/b0b46bae7f9308a68af4 to your computer and use it in GitHub Desktop.
Prints the size of each modules included in a webpack bundle

Prints the size of each modules included in a webpack bundle. Add pathinfo: true, in the output property of your webpack configuration, then run node webpack-packages-size.js path_to_the_bundle.js.

"use strict";
const EventEmitter = require("events").EventEmitter;
const fs = require("fs");
function parseWebpackModuleName(name) {
if (!name) name = "";
const chunks = name.split("/");
if (chunks[0] === ".") {
// Root package
return {
package: [],
path: chunks.slice(1).join("/"),
};
}
if (chunks[0] === "..") {
// External package
const lastPackageIndex = chunks.lastIndexOf("~") + 2;
return {
package: chunks.slice(1, lastPackageIndex).filter((chunk) => chunk !== "~"),
path: chunks.slice(lastPackageIndex).join("/"),
};
}
return {
package: ["webpack"],
path: "<none>",
};
}
class FileStreamer extends EventEmitter {
constructor(bundlePath) {
super();
const stream = fs.createReadStream(bundlePath, {
encoding: "utf-8",
});
stream.on("error", (e) => this.emit("error", e));
let leftoverData = "";
let currentFileName;
const re = /\/\*\!\**\!\*\\\n {2}\!\*\*\*\ ([^\n]+?) \*\*\*\!\n {2}\\\**\/\n/g;
const emitFile = (data) => {
this.emit("file", Object.assign({
data: data,
}, parseWebpackModuleName(currentFileName)));
};
stream.on("data", (data) => {
data = leftoverData + data;
let lastIndex = 0;
while (true) {
const match = re.exec(data);
if (!match) break;
emitFile(data.slice(lastIndex, match.index));
currentFileName = match[1];
lastIndex = re.lastIndex;
}
leftoverData = data.slice(lastIndex);
});
stream.on("end", () => {
emitFile(leftoverData);
this.emit("end");
});
}
}
const file = process.argv[2];
const stream = new FileStreamer(file);
const map = new Map();
stream.on("file", (event) => {
const packageName = event.package && event.package.join("/");
if (map.has(packageName)) map.set(packageName, map.get(packageName) + event.data.length);
else map.set(packageName, event.data.length);
});
stream.on("error", (error) => {
console.log(error.stack);
});
function pad(value, n) {
const p = Array(Math.abs(n) + 1).join(" ");
return n > 0 ? (value + p).slice(0, n) : (p + value).slice(n);
}
function formatInteger(n) {
n = String(Math.floor(n))
let result = ""
let i = n.length
for (; i > 0; i -= 3) {
result = n.slice(i - 3, i) + (result ? "." : "") + result
}
result = n.slice(0, 3 + i) + result
return result
}
stream.on("end", () => {
const keys = Array.from(map.keys()).sort()
const keyPadding = Math.max(...keys.map((k) => String(k).length))
const valuePadding = Math.max(...Array.from(map.values()).map((v) => formatInteger(v).length))
for (const key of keys) {
console.log(pad(key, keyPadding),
pad(formatInteger(map.get(key)), -valuePadding));
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment