diff --git a/package.json b/package.json index 0e884945..723df2fa 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "devDependencies": { "@babel/core": "^7.1.6", "@svgr/webpack": "^2.4.1", - "adm-zip": "^0.4.11", + "adm-zip": "0.4.11", "autoprefixer": "^7.1.6", "babel-core": "7.0.0-bridge.0", "babel-eslint": "^10.0.1", diff --git a/scripts/build.js b/scripts/build.js index 79e88919..8c0a933e 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,4 +1,4 @@ -/* eslint no-console: "off" */ +/* eslint-disable no-console */ // Do this as the first thing so that any code reading it knows the right env. process.env.BABEL_ENV = 'production'; @@ -18,14 +18,16 @@ const path = require('path'); const chalk = require('chalk'); const fs = require('fs-extra'); const webpack = require('webpack'); +const bfj = require('bfj'); +const AdmZip = require('adm-zip'); const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); const printHostingInstructions = require('react-dev-utils/printHostingInstructions'); const FileSizeReporter = require('react-dev-utils/FileSizeReporter'); const printBuildError = require('react-dev-utils/printBuildError'); -const AdmZip = require('adm-zip'); +const { checkBrowsers } = require('react-dev-utils/browsersHelper'); const paths = require('../config/paths'); -const config = require('../config/webpack.config.prod'); +const configFactory = require('../config/webpack.config'); const { measureFileSizesBeforeBuild, printFileSizesAfterBuild } = FileSizeReporter; const useYarn = fs.existsSync(paths.yarnLockFile); @@ -34,14 +36,27 @@ const useYarn = fs.existsSync(paths.yarnLockFile); const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; // eslint-disable-line const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; // eslint-disable-line +const isInteractive = process.stdout.isTTY; + // Warn and crash if required files are missing if (!checkRequiredFiles([ paths.appHtml, paths.appIndexJs ])) { process.exit(1); } -// First, read the current file sizes in build directory. -// This lets us display how much they changed later. -measureFileSizesBeforeBuild(paths.appBuild) +// Process CLI arguments +const argvSliceStart = 2; +const argv = process.argv.slice(argvSliceStart); +const writeStatsJson = argv.indexOf('--stats') !== -1; + +// Generate configuration +const config = configFactory('production'); + +checkBrowsers(paths.appPath, isInteractive) + .then(() => + + // First, read the current file sizes in build directory. + // This lets us display how much they changed later. + 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 @@ -85,7 +100,7 @@ measureFileSizesBeforeBuild(paths.appBuild) const appPackage = require(paths.appPackageJson); const { publicUrl } = paths; - const { publicPath } = config.output; + const { output: { publicPath } } = config; const buildFolder = path.relative(process.cwd(), paths.appBuild); printHostingInstructions( @@ -103,7 +118,13 @@ measureFileSizesBeforeBuild(paths.appBuild) } ) .then(zipDist) - .catch((err) => console.error(err)); + .catch((err) => { + if (err && err.message) { + console.log(err.message); + } + + process.exit(1); + }); // Create the production build and print the deployment instructions. function build(previousFileSizes) { @@ -113,12 +134,22 @@ function build(previousFileSizes) { return new Promise((resolve, reject) => { compiler.run((err, stats) => { + let messages; + if (err) { - return reject(err); + if (!err.message) { + return reject(err); + } + + messages = formatWebpackMessages({ + errors: [ err.message ], + warnings: [], + }); + } else { + messages = formatWebpackMessages( + stats.toJson({ all: false, warnings: true, errors: true }) + ); } - - const messages = formatWebpackMessages(stats.toJson({}, true)); - if (messages.errors.length) { // Only keep the first error. Others are often indicative // of the same problem, but confuse the reader with noise. @@ -144,11 +175,20 @@ function build(previousFileSizes) { return reject(new Error(messages.warnings.join('\n\n'))); } - return resolve({ + const resolveArgs = { stats, previousFileSizes, warnings: messages.warnings, - }); + }; + + if (writeStatsJson) { + return bfj // eslint-disable-line promise/no-promise-in-callback + .write(`${paths.appBuild}/bundle-stats.json`, stats.toJson()) + .then(() => resolve(resolveArgs)) + .catch((error) => reject(new Error(error))); + } + + return resolve(resolveArgs); }); }); } diff --git a/yarn.lock b/yarn.lock index 97e84fd6..34d65aae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1064,9 +1064,9 @@ address@1.0.3, address@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" -adm-zip@^0.4.11: - version "0.4.13" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.13.tgz#597e2f8cc3672151e1307d3e95cddbc75672314a" +adm-zip@0.4.11: + version "0.4.11" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a" ajv-errors@^1.0.0: version "1.0.1"