UNPKG

2.96 kBJavaScriptView Raw
1import * as colors from 'kleur/colors';
2/** The minimum width, in characters, of each size column */
3const SIZE_COLUMN_WIDTH = 11;
4/** Generic Object.entries() alphabetical sort by keys. */
5function entriesSort([filenameA], [filenameB]) {
6 return filenameA.localeCompare(filenameB);
7}
8/** Pretty-prints number of bytes as "XXX KB" */
9function formatSize(size) {
10 let kb = Math.round((size / 1000) * 100) / 100;
11 if (kb >= 1000) {
12 kb = Math.floor(kb);
13 }
14 let color;
15 if (kb < 15) {
16 color = 'green';
17 }
18 else if (kb < 30) {
19 color = 'yellow';
20 }
21 else {
22 color = 'red';
23 }
24 return colors[color](`${kb} KB`.padEnd(SIZE_COLUMN_WIDTH));
25}
26function formatDelta(delta) {
27 const kb = Math.round(delta * 100) / 100;
28 const color = delta > 0 ? 'red' : 'green';
29 return colors[color](${delta > 0 ? '+' : ''}${kb} KB`);
30}
31function formatFileInfo(filename, stats, padEnd, isLastFile) {
32 const lineGlyph = colors.dim(isLastFile ? '└─' : '├─');
33 const lineName = filename.padEnd(padEnd);
34 const fileStat = formatSize(stats.size);
35 const gzipStat = formatSize(stats.gzip);
36 const brotliStat = formatSize(stats.brotli);
37 const lineStat = fileStat + gzipStat + brotliStat;
38 let lineDelta = '';
39 if (stats.delta) {
40 lineDelta = colors.dim('[') + formatDelta(stats.delta) + colors.dim(']');
41 }
42 // Trim trailing whitespace (can mess with formatting), but keep indentation.
43 return ` ` + `${lineGlyph} ${lineName} ${lineStat} ${lineDelta}`.trim();
44}
45function formatFiles(files, padEnd) {
46 const strippedFiles = files.map(([filename, stats]) => [
47 filename.replace(/^common\//, ''),
48 stats,
49 ]);
50 return strippedFiles
51 .map(([filename, stats], index) => formatFileInfo(filename, stats, padEnd, index >= files.length - 1))
52 .join('\n');
53}
54export function printStats(dependencyStats) {
55 let output = '';
56 const { direct, common } = dependencyStats;
57 const allDirect = Object.entries(direct).sort(entriesSort);
58 const allCommon = Object.entries(common).sort(entriesSort);
59 const maxFileNameLength = [...allCommon, ...allDirect].reduce((max, [filename]) => Math.max(filename.length, max), 'web_modules/'.length) + 1;
60 output +=
61 ` ⦿ ${colors.bold('web_modules/'.padEnd(maxFileNameLength + 4))}` +
62 colors.bold(colors.underline('size'.padEnd(SIZE_COLUMN_WIDTH - 2))) +
63 ' ' +
64 colors.bold(colors.underline('gzip'.padEnd(SIZE_COLUMN_WIDTH - 2))) +
65 ' ' +
66 colors.bold(colors.underline('brotli'.padEnd(SIZE_COLUMN_WIDTH - 2))) +
67 `\n`;
68 output += `${formatFiles(allDirect, maxFileNameLength)}\n`;
69 if (Object.values(common).length > 0) {
70 output += ` ⦿ ${colors.bold('web_modules/common/ (Shared)')}\n`;
71 output += `${formatFiles(allCommon, maxFileNameLength)}\n`;
72 }
73 return `\n${output}\n`;
74}