webpack-dashboard/utils/format-modules.js
2019-05-15 12:21:09 -07:00

85 lines
2.4 KiB
JavaScript

"use strict";
/**
* Modules are the individual files within an asset.
*/
const { relative, resolve, sep } = require("path");
const filesize = require("filesize");
const PERCENT_MULTIPLIER = 100;
const PERCENT_PRECISION = 3;
// Convert to:
// - existing source file name
// - the path leading up to **just** the package (not including subpath).
function _formatFileName(mod) {
const { fileName, baseName } = mod;
// Source file.
if (!baseName) {
return `{green-fg}.${sep}${relative(process.cwd(), resolve(fileName))}{/}`;
}
// Package
let parts = fileName.split(sep);
// Remove starting path.
const firstNmIdx = parts.indexOf("node_modules");
parts = parts.slice(firstNmIdx);
// Remove trailing path after package.
const lastNmIdx = parts.lastIndexOf("node_modules");
const isScoped = (parts[lastNmIdx + 1] || "").startsWith("@");
parts = parts.slice(0, lastNmIdx + (isScoped ? 3 : 2)); // eslint-disable-line no-magic-numbers
return parts.map(part => (part === "node_modules" ? "~" : `{yellow-fg}${part}{/}`)).join(sep);
}
function _formatPercentage(modSize, assetSize) {
const percentage = ((modSize / assetSize) * PERCENT_MULTIPLIER).toPrecision(PERCENT_PRECISION);
return `${percentage}%`;
}
function formatModules(mods) {
// We _could_ use the `asset.meta.full` from inspectpack, but that is for
// the entire module with boilerplate included. We instead do a percentage
// of the files we're counting here.
const assetSize = mods.reduce((count, mod) => count + mod.size.full, 0);
// First, process the modules into a map to normalize file paths.
const modsMap = mods.reduce((memo, mod) => {
// File name collapses to packages for dependencies.
// Aggregate into object.
const fileName = _formatFileName(mod);
// Add in information.
memo[fileName] = memo[fileName] || {
fileName,
num: 0,
size: 0
};
memo[fileName].num += 1;
memo[fileName].size += mod.size.full;
return memo;
}, {});
return [].concat(
[["Name", "Size", "Percent"]],
Object.keys(modsMap)
.map(fileName => modsMap[fileName])
.sort((a, b) => a.size < b.size) // sort largest first
.map(mod => [
`${mod.fileName} ${mod.num > 1 ? `(${mod.num})` : ""}`,
filesize(mod.size),
_formatPercentage(mod.size, assetSize)
])
);
}
module.exports = {
formatModules,
_formatFileName,
_formatPercentage
};