1 | import * as colors from 'kleur/colors';
|
2 |
|
3 | const SIZE_COLUMN_WIDTH = 11;
|
4 |
|
5 | function entriesSort([filenameA], [filenameB]) {
|
6 | return filenameA.localeCompare(filenameB);
|
7 | }
|
8 |
|
9 | function 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 | }
|
26 | function 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 | }
|
31 | function 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 |
|
43 | return ` ` + `${lineGlyph} ${lineName} ${lineStat} ${lineDelta}`.trim();
|
44 | }
|
45 | function 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 | }
|
54 | export 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 | }
|