build.js (4101B)
1 'use strict'; 2 3 const chalk = require('chalk'); 4 const execSync = require('child_process').execSync; 5 const filesize = require('filesize').filesize; 6 const fs = require('fs-extra'); 7 const gzipSize = require('gzip-size').sync; 8 const path = require('path'); 9 const recursive = require('recursive-readdir'); 10 11 const paths = require('../webpack/paths'); 12 13 const errorExitStatus = 1; 14 15 function getVersionFromGit() { 16 const verCmd = 17 'echo -n ' + 18 '`date +%Y-%m-%d_%H:%M:%S`-' + 19 '`git rev-parse --abbrev-ref HEAD`-' + 20 '`git rev-parse --short HEAD`' + 21 '`git diff-index --quiet HEAD -- || echo -dirty`'; 22 return execSync(verCmd).toString(); 23 } 24 25 // Input: /User/dan/app/build/static/js/main.82be8.js 26 // Output: /static/js/main.js 27 function removeFileNameHash(fileName) { 28 return fileName.replace(/\/?(.*)(\.[0-9a-f]+)(\.js|\.css)/u, (match, p1, p2, p3) => p1 + p3); 29 } 30 31 function getSizes(removeNameHash) { 32 return new Promise((resolve) => { 33 recursive(paths.appBuild, (err, fileNames) => { 34 const previousSizeMap = (fileNames || []) 35 .filter((fileName) => /\.(js|css)$/u.test(fileName)) 36 .reduce((memo, fileName) => { 37 const contents = fs.readFileSync(fileName); 38 const relativeFileName = fileName.replace(paths.appBuild + '/', ''); 39 const key = removeNameHash ? removeFileNameHash(relativeFileName) : relativeFileName; 40 memo[key] = gzipSize(contents); 41 return memo; 42 }, {}); 43 resolve(previousSizeMap); 44 }); 45 }); 46 } 47 48 // Print a detailed summary of build files. 49 function printFileSizes(sizeMap, previousSizeMap) { 50 const ASSET_DIFF_SIZE_WARNING_THRESHOLD = 50000; 51 const assets = Object.entries(sizeMap).map(([filename, size]) => { 52 const difference = size - (previousSizeMap[removeFileNameHash(filename)] || 0); 53 return { 54 folder: path.join('build', path.dirname(filename)), 55 name: path.basename(filename), 56 size: size, 57 difference: difference, 58 }; 59 }); 60 assets.sort((a, b) => b.size - a.size); 61 for (const asset of assets) { 62 const sizeLabel = ' ' + filesize(asset.size); 63 let differenceLabel = ''; 64 let labelSize = sizeLabel.length; 65 if (asset.difference !== 0) { 66 let differenceColor; 67 if (asset.difference > ASSET_DIFF_SIZE_WARNING_THRESHOLD) { 68 differenceColor = chalk.red; 69 } else if (asset.difference > 0) { 70 differenceColor = chalk.yellow; 71 } else { 72 differenceColor = chalk.green; 73 } 74 differenceLabel = filesize(asset.difference); 75 if (asset.difference > 0) { 76 differenceLabel = '+' + differenceLabel; 77 } 78 labelSize += differenceLabel.length; 79 differenceLabel = differenceColor(differenceLabel); 80 differenceLabel = ` (${differenceLabel})`; 81 const labelSizeAllowance = 4; 82 labelSize += labelSizeAllowance; 83 } 84 const maxLabelSize = 30; 85 const padding = ' '.repeat(Math.max(maxLabelSize - labelSize, 0)); 86 console.log( 87 sizeLabel + differenceLabel + padding + chalk.dim(asset.folder + path.sep) + chalk.cyan(asset.name) 88 ); 89 } 90 } 91 92 async function main() { 93 process.env.NODE_ENV = 'production'; 94 const version = getVersionFromGit(); 95 process.env.RELEASE_VER = version; 96 console.log('Creating an optimized production build...'); 97 console.log('Version:', version); 98 const prevSizes = await getSizes(true); 99 try { 100 execSync('webpack --config webpack/webpack.config.js --color --progress=profile', { 101 stdio: 'inherit', 102 }); 103 } catch (e) { 104 process.exit(errorExitStatus); 105 } 106 console.log(chalk.green('Compiled successfully.')); 107 const newSizes = await getSizes(false); 108 console.log('File sizes after gzip:\n'); 109 printFileSizes(newSizes, prevSizes); 110 } 111 112 main();