diff --git a/package.json b/package.json index 4f49a5c89c2..f4087f6240f 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,8 @@ "html-webpack-plugin": "2.22.0", "jest": "14.1.0", "json-loader": "0.5.4", + "memory-fs": "^0.3.0", + "mkdirp": "^0.5.1", "opn": "4.0.2", "postcss-loader": "0.9.1", "promise": "7.1.1", diff --git a/scripts/build.js b/scripts/build.js index e57e040bd6e..fdec283132b 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -14,17 +14,51 @@ var fs = require('fs'); var path = require('path'); var filesize = require('filesize'); var gzipSize = require('gzip-size').sync; +var MemoryFS = require('memory-fs'); +var mkdirpSync = require('mkdirp').sync; var rimrafSync = require('rimraf').sync; var webpack = require('webpack'); var config = require('../config/webpack.config.prod'); var paths = require('../config/paths'); -// Remove all content but keep the directory so that -// if you're in it, you don't end up in Trash -rimrafSync(paths.appBuild + '/*'); - console.log('Creating an optimized production build...'); -webpack(config).run(function(err, stats) { + +var memFs = new MemoryFS(); +var compiler = webpack(config); +compiler.outputFileSystem = memFs; + +compiler.run(function(err, stats) { + var statsAssets = stats.toJson().assets; + + // Read old assets from the file system + var oldAssets = statsAssets + .filter(asset => /\.(js|css)$/.test(asset.name)) + .map(asset => { + try { + var fileContents = fs.readFileSync(paths.appBuild + '/' + asset.name); + var size = gzipSize(fileContents); + return { + fullName: asset.name, + size: size + }; + } catch (e) { + return {}; + } + }); + + // Remove all content but keep the directory so that + // if you're in it, you don't end up in Trash + rimrafSync(paths.appBuild + '/*'); + + // Write new assets to the file system + statsAssets + .map(asset => { + var fileFullPath = paths.appBuild + '/' + asset.name; + var fileContents = memFs.readFileSync(fileFullPath); + mkdirpSync(path.dirname(fileFullPath)); + fs.writeFileSync(fileFullPath, fileContents); + }); + if (err) { console.error('Failed to create a production build. Reason:'); console.error(err.message || err); @@ -36,16 +70,32 @@ webpack(config).run(function(err, stats) { console.log('File sizes after gzip:'); console.log(); - var assets = stats.toJson().assets + var assets = statsAssets .filter(asset => /\.(js|css)$/.test(asset.name)) .map(asset => { var fileContents = fs.readFileSync(paths.appBuild + '/' + asset.name); var size = gzipSize(fileContents); + var sizeDiffLabel = ''; + + for (var i = oldAssets.length - 1; i >= 0; --i) { + var oldAsset = oldAssets[i]; + if (oldAsset.fullName === asset.name) { + var sizeDiff = size - oldAsset.size; + if (sizeDiff !== 0) { + sizeDiffLabel = ' (' + + (sizeDiff < 0 ? '-' : '+') + + filesize(Math.abs(sizeDiff)) + + ')'; + } + break; + } + } + return { folder: path.join('build', path.dirname(asset.name)), name: path.basename(asset.name), size: size, - sizeLabel: filesize(size) + sizeLabel: filesize(size) + sizeDiffLabel }; }); assets.sort((a, b) => b.size - a.size);