webpack-dashboard/utils/format-modules.js
Ryan Roemer 8a32cd19ff
[Major] Integrate inspectpack3 - faster, better, and more colorful! (#249)
This is a major update to `webpack-dashboard` with breaking changes. And a lot of speed and coolness.

## Breaking changes

- Requires node6+.
- Use the webpack internal stats object instead of real bundles. This is faster and with less futzing / parsing on the dashboard's end. Should permanently fix the `no code sections` found errors.
- We've removed command flags / plugin options that no longer apply like `--root`, etc.

### Modules

- Removed `min` and `min+gz` estimated file sizes from modules outputs. This dramatically speeds up the dashboard and reduces CPU usage.

### Versions

- Version skews should be detected more accurately and much faster thanks to dramatically improved heuristics from `inspectpack`.

### Duplicates

- Duplicates now reports on duplicate files that are (1) completely identical, and (2) the same package name and file path but with different sources. The first are low hanging fruit for optimizations in your build -- you've literally got the same thing multiple times. The latter needs to be coalesced at the package dependency level -- something the versions output can help with.

## Issues

- Upgrade hooks to work in webpack1-4 with abstraction. Fixes #240

## Refactoring

- Switch from `chalk` to using Blessed's built-in tags for coloring. This is definitely the way to go as things like table spacing don't work with chalk strings and work like a charm with Blessed tags.
- Update dependencies and remove lots of unused things (like `lodash`, `chalk`, `bluebird` and a whole lot of `babel*` that apparently wasn't used anyways).
    - New `inspectpack` is way slimmer and faster, with no more binary dependencies!
- Switch to yarn-only workflow in dev.
- Bump Travis node versions.
2018-05-24 13:12:52 -07:00

83 lines
2.3 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}./${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;