From 07fed0450dc1c76543b90e38da161394c321f5bd Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 6 Mar 2017 01:17:05 +0000 Subject: [PATCH] Tweak APIs and fix issues --- packages/react-dev-utils/FileSizeReporter.js | 69 +++++++++++++------- packages/react-dev-utils/README.md | 23 +++++++ packages/react-dev-utils/package.json | 23 +++---- packages/react-scripts/package.json | 4 -- packages/react-scripts/scripts/build.js | 30 ++++----- 5 files changed, 93 insertions(+), 56 deletions(-) diff --git a/packages/react-dev-utils/FileSizeReporter.js b/packages/react-dev-utils/FileSizeReporter.js index 5f71f21977d..44c972c4546 100644 --- a/packages/react-dev-utils/FileSizeReporter.js +++ b/packages/react-dev-utils/FileSizeReporter.js @@ -1,18 +1,33 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +'use strict'; + var fs = require('fs'); var path = require('path'); var chalk = require('chalk'); var filesize = require('filesize'); +var recursive = require('recursive-readdir'); var stripAnsi = require('strip-ansi'); var gzipSize = require('gzip-size').sync; -// Print a detailed summary of build files. -function printFileSizesAfterBuild(appBuild, stats, previousSizeMap) { - var assets = stats + +// Prints a detailed summary of build files. +function printFileSizesAfterBuild(webpackStats, previousSizeMap) { + var root = previousSizeMap.root; + var sizes = previousSizeMap.sizes; + var assets = webpackStats .toJson() .assets.filter(asset => /\.(js|css)$/.test(asset.name)) .map(asset => { - var fileContents = fs.readFileSync(appBuild + '/' + asset.name); + var fileContents = fs.readFileSync(path.join(root, asset.name)); var size = gzipSize(fileContents); - var previousSize = previousSizeMap[removeFileNameHash(appBuild, asset.name)]; + var previousSize = sizes[removeFileNameHash(root, asset.name)]; var difference = getDifferenceLabel(size, previousSize); return { folder: path.join('build', path.dirname(asset.name)), @@ -41,13 +56,13 @@ function printFileSizesAfterBuild(appBuild, stats, previousSizeMap) { chalk.cyan(asset.name) ); }); -}; +} -function removeFileNameHash(appBuild, fileName) { +function removeFileNameHash(buildFolder, fileName) { return fileName - .replace(appBuild, '') + .replace(buildFolder, '') .replace(/\/?(.*)(\.\w+)(\.js|\.css)/, (match, p1, p2, p3) => p1 + p3); -}; +} // Input: 1024, 2048 // Output: "(+1 KB)" @@ -64,22 +79,32 @@ function getDifferenceLabel(currentSize, previousSize) { } else { return ''; } -}; +} -function measureFileSizesBeforeBuild(appBuild, fileNames){ - return (fileNames || []) - .filter(fileName => /\.(js|css)$/.test(fileName)) - .reduce((memo, fileName) => { - var contents = fs.readFileSync(fileName); - var key = removeFileNameHash(appBuild, fileName); - memo[key] = gzipSize(contents); - return memo; - }, {}); +function measureFileSizesBeforeBuild(buildFolder) { + return new Promise(resolve => { + recursive(buildFolder, (err, fileNames) => { + var sizes; + if (!err && fileNames) { + sizes = fileNames + .filter(fileName => /\.(js|css)$/.test(fileName)) + .reduce((memo, fileName) => { + var contents = fs.readFileSync(fileName); + var key = removeFileNameHash(buildFolder, fileName); + memo[key] = gzipSize(contents); + return memo; + }, {}); + } + resolve({ + root: buildFolder, + sizes: sizes || {}, + }); + }); + }); } module.exports = { measureFileSizesBeforeBuild: measureFileSizesBeforeBuild, - printFileSizesAfterBuild: printFileSizesAfterBuild -} - + printFileSizesAfterBuild: printFileSizesAfterBuild, +}; diff --git a/packages/react-dev-utils/README.md b/packages/react-dev-utils/README.md index 2d430e2a299..0245c7e8086 100644 --- a/packages/react-dev-utils/README.md +++ b/packages/react-dev-utils/README.md @@ -110,6 +110,29 @@ clearConsole(); console.log('Just cleared the screen!'); ``` +#### `FileSizeReporter` + +##### `measureFileSizesBeforeBuild(buildFolder: string): Promise` + +Captures JS and CSS asset sizes inside the passed `buildFolder`. Save the result value to compare it after the build. + +#### `printFileSizesAfterBuild(webpackStats: WebpackStats, previousFileSizes: OpaqueFileSizes)` + +Prints the JS and CSS asset sizes after the build, and includes a size comparison with `previousFileSizes` that were captured earlier using `measureFileSizesBeforeBuild()`. + +```js +var { + measureFileSizesBeforeBuild, + printFileSizesAfterBuild, +} = require('react-dev-utils/FileSizeReporter'); + +measureFileSizesBeforeBuild(buildFolder).then(previousFileSizes => { + return cleanAndRebuild().then(webpackStats => { + printFileSizesAfterBuild(webpackStats, previousFileSizes); + }); +}); +``` + #### `formatWebpackMessages({errors: Array, warnings: Array}): {errors: Array, warnings: Array}` Extracts and prettifies warning and error messages from webpack [stats](https://github.com/webpack/docs/wiki/node.js-api#stats) object. diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 147ecf7bd16..35c490be84d 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -11,17 +11,17 @@ "node": ">=4" }, "files": [ - "checkRequiredFiles.js", - "clearConsole.js", - "formatWebpackMessages.js", - "getProcessForPort.js", - "InterpolateHtmlPlugin.js", - "openBrowser.js", - "openChrome.applescript", - "printFileSizes.js", + "checkRequiredFiles.js", + "clearConsole.js", + "FileSizeReporter.js", + "formatWebpackMessages.js", + "getProcessForPort.js", + "InterpolateHtmlPlugin.js", + "openBrowser.js", + "openChrome.applescript", "prompt.js", - "removeFileNameHash.js", - "WatchMissingNodeModulesPlugin.js", + "removeFileNameHash.js", + "WatchMissingNodeModulesPlugin.js", "webpackHotDevClient.js" ], "dependencies": { @@ -29,9 +29,10 @@ "chalk": "1.1.3", "escape-string-regexp": "1.0.5", "filesize": "3.3.0", - "gzip-size": "^3.0.0", + "gzip-size": "3.0.0", "html-entities": "1.2.0", "opn": "4.0.2", + "recursive-readdir": "2.1.1", "sockjs-client": "1.1.2", "strip-ansi": "3.0.1" } diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index e0ae953e95f..17a1c2fe59a 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -46,9 +46,7 @@ "eslint-plugin-react": "6.4.1", "extract-text-webpack-plugin": "2.0.0", "file-loader": "0.10.0", - "filesize": "3.3.0", "fs-extra": "0.30.0", - "gzip-size": "3.0.0", "html-webpack-plugin": "2.28.0", "http-proxy-middleware": "0.17.3", "jest": "18.1.0", @@ -56,8 +54,6 @@ "postcss-loader": "1.3.1", "promise": "7.1.1", "react-dev-utils": "^0.5.1", - "recursive-readdir": "2.1.1", - "strip-ansi": "3.0.1", "style-loader": "0.13.1", "url-loader": "0.5.7", "webpack": "2.2.1", diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js index 34f5f23338f..1e54d38ef7c 100644 --- a/packages/react-scripts/scripts/build.js +++ b/packages/react-scripts/scripts/build.js @@ -22,15 +22,13 @@ var chalk = require('chalk'); var fs = require('fs-extra'); var path = require('path'); var url = require('url'); -var filesize = require('filesize'); -var gzipSize = require('gzip-size').sync; var webpack = require('webpack'); var config = require('../config/webpack.config.prod'); var paths = require('../config/paths'); var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); -var fileSizeReporter = require('react-dev-utils/fileSizeReporter'); -var recursive = require('recursive-readdir'); -var stripAnsi = require('strip-ansi'); +var FileSizeReporter = require('react-dev-utils/FileSizeReporter'); +var measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild; +var printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild; var useYarn = fs.existsSync(paths.yarnLockFile); @@ -41,22 +39,16 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { // First, read the current file sizes in build directory. // This lets us display how much they changed later. -recursive(paths.appBuild, (err, fileNames) => { - var previousSizeMap = fileSizeReporter.measureFileSizesBeforeBuild(paths.appBuild, fileNames); - +measureFileSizesBeforeBuild(paths.appBuild).then(previousFileSizes => { // Remove all content but keep the directory so that // if you're in it, you don't end up in Trash fs.emptyDirSync(paths.appBuild); // Start the webpack build - build(previousSizeMap); + build(previousFileSizes); // Merge with the public folder - copyPublicFolder( - paths.appPublic, - paths.appBuild, - paths.appHtml - ); + copyPublicFolder(); }); // Print out errors @@ -70,7 +62,7 @@ function printErrors(summary, errors) { } // Create the production build and print the deployment instructions. -function build(previousSizeMap) { +function build(previousFileSizes) { console.log('Creating an optimized production build...'); var compiler; @@ -102,7 +94,7 @@ function build(previousSizeMap) { console.log('File sizes after gzip:'); console.log(); - fileSizeReporter.printFileSizesAfterBuild(paths.appBuild, stats, previousSizeMap); + printFileSizesAfterBuild(stats, previousFileSizes); console.log(); var openCommand = process.platform === 'win32' ? 'start' : 'open'; @@ -178,10 +170,10 @@ function build(previousSizeMap) { }); } -function copyPublicFolder(appPublic, appBuild, appHtml) { - fs.copySync(appPublic, appBuild, { +function copyPublicFolder() { + fs.copySync(paths.appPublic, paths.appBuild, { dereference: true, - filter: file => file !== appHtml + filter: file => file !== paths.appHtml }); };