main
js 126 lines 3.24 KB
Raw
1 'use strict';
2
3 const Table = require('cli-table');
4 const filesize = require('filesize');
5 const chalk = require('chalk');
6 const join = require('path').join;
7 const fs = require('fs');
8 const mkdirp = require('mkdirp');
9
10 const BUNDLE_SIZES_FILE_NAME = join(__dirname, '../../build/bundle-sizes.json');
11 const prevBuildResults = fs.existsSync(BUNDLE_SIZES_FILE_NAME)
12 ? require(BUNDLE_SIZES_FILE_NAME)
13 : {bundleSizes: []};
14
15 const currentBuildResults = {
16 // Mutated inside build.js during a build run.
17 bundleSizes: [],
18 };
19
20 function saveResults() {
21 if (process.env.CI === true) {
22 mkdirp.sync('build/sizes');
23 fs.writeFileSync(
24 join('build', 'sizes', `bundle-sizes-${process.env.NODE_INDEX}.json`),
25 JSON.stringify(currentBuildResults, null, 2)
26 );
27 } else {
28 // Write all the bundle sizes to a single JSON file.
29 fs.writeFileSync(
30 BUNDLE_SIZES_FILE_NAME,
31 JSON.stringify(currentBuildResults, null, 2)
32 );
33 }
34 }
35
36 function fractionalChange(prev, current) {
37 return (current - prev) / prev;
38 }
39
40 function percentChangeString(change) {
41 if (!isFinite(change)) {
42 // When a new package is created
43 return 'n/a';
44 }
45 const formatted = (change * 100).toFixed(1);
46 if (/^-|^0(?:\.0+)$/.test(formatted)) {
47 return `${formatted}%`;
48 } else {
49 return `+${formatted}%`;
50 }
51 }
52
53 const resultsHeaders = [
54 'Bundle',
55 'Prev Size',
56 'Current Size',
57 'Diff',
58 'Prev Gzip',
59 'Current Gzip',
60 'Diff',
61 ];
62
63 function generateResultsArray(current, prevResults) {
64 return current.bundleSizes
65 .map(result => {
66 const prev = prevResults.bundleSizes.filter(
67 res =>
68 res.filename === result.filename &&
69 res.bundleType === result.bundleType
70 )[0];
71 if (result === prev) {
72 // We didn't rebuild this bundle.
73 return;
74 }
75
76 const size = result.size;
77 const gzip = result.gzip;
78 let prevSize = prev ? prev.size : 0;
79 let prevGzip = prev ? prev.gzip : 0;
80
81 return {
82 filename: result.filename,
83 bundleType: result.bundleType,
84 packageName: result.packageName,
85 prevSize: filesize(prevSize),
86 prevFileSize: filesize(size),
87 prevFileSizeChange: fractionalChange(prevSize, size),
88 prevFileSizeAbsoluteChange: size - prevSize,
89 prevGzip: filesize(prevGzip),
90 prevGzipSize: filesize(gzip),
91 prevGzipSizeChange: fractionalChange(prevGzip, gzip),
92 prevGzipSizeAbsoluteChange: gzip - prevGzip,
93 };
94 // Strip any nulls
95 })
96 .filter(f => f);
97 }
98
99 function printResults() {
100 const table = new Table({
101 head: resultsHeaders.map(label => chalk.gray.yellow(label)),
102 });
103
104 const results = generateResultsArray(currentBuildResults, prevBuildResults);
105 results.forEach(result => {
106 table.push([
107 chalk.white.bold(`${result.filename} (${result.bundleType})`),
108 chalk.gray.bold(result.prevSize),
109 chalk.white.bold(result.prevFileSize),
110 percentChangeString(result.prevFileSizeChange),
111 chalk.gray.bold(result.prevGzip),
112 chalk.white.bold(result.prevGzipSize),
113 percentChangeString(result.prevGzipSizeChange),
114 ]);
115 });
116
117 return table.toString();
118 }
119
120 module.exports = {
121 currentBuildResults,
122 generateResultsArray,
123 printResults,
124 saveResults,
125 resultsHeaders,
126 };