on 0cb7c34 help sign in
bridge/scripts/build.js
191 lines 6.2 kB history raw
1'use strict';
3// Do this as the first thing so that any code reading it knows the right env.
4process.env.BABEL_ENV = 'production';
5process.env.NODE_ENV = 'production';
7// Makes the script crash on unhandled rejections instead of silently
8// ignoring them. In the future, promise rejections that are not handled will
9// terminate the Node.js process with a non-zero exit code.
10process.on('unhandledRejection', err => {
11 throw err;
12});
14// Ensure environment variables are read.
15require('../config/env');
18const path = require('path');
19const chalk = require('react-dev-utils/chalk');
20const fs = require('fs-extra');
21const webpack = require('webpack');
22const configFactory = require('../config/webpack.config');
23const paths = require('../config/paths');
24const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
25const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
26const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
27const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
28const printBuildError = require('react-dev-utils/printBuildError');
30const measureFileSizesBeforeBuild =
31 FileSizeReporter.measureFileSizesBeforeBuild;
32const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
33const useYarn = fs.existsSync(paths.yarnLockFile);
35// These sizes are pretty large. We'll warn for bundles exceeding them.
36const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
37const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
39const isInteractive = process.stdout.isTTY;
41// Warn and crash if required files are missing
42if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
43 process.exit(1);
46// Generate configuration
47const config = configFactory('production');
49// We require that you explicitly set browsers and do not fall back to
50// browserslist defaults.
51const { checkBrowsers } = require('react-dev-utils/browsersHelper');
52checkBrowsers(paths.appPath, isInteractive)
53 .then(() => {
54 // First, read the current file sizes in build directory.
55 // This lets us display how much they changed later.
56 return measureFileSizesBeforeBuild(paths.appBuild);
57 })
58 .then(previousFileSizes => {
59 // Remove all content but keep the directory so that
60 // if you're in it, you don't end up in Trash
61 fs.emptyDirSync(paths.appBuild);
62 // Merge with the public folder
63 copyPublicFolder();
64 // Start the webpack build
65 return build(previousFileSizes);
66 })
67 .then(
68 ({ stats, previousFileSizes, warnings }) => {
69 if (warnings.length) {
70 console.log(chalk.yellow('Compiled with warnings.\n'));
71 console.log(warnings.join('\n\n'));
72 console.log(
73 '\nSearch for the ' +
74 chalk.underline(chalk.yellow('keywords')) +
75 ' to learn more about each warning.'
76 );
77 console.log(
78 'To ignore, add ' +
79 chalk.cyan('// eslint-disable-next-line') +
80 ' to the line before.\n'
81 );
82 } else {
83 console.log(chalk.green('Compiled successfully.\n'));
84 }
86 console.log('File sizes after gzip:\n');
87 printFileSizesAfterBuild(
88 stats,
89 previousFileSizes,
90 paths.appBuild,
91 WARN_AFTER_BUNDLE_GZIP_SIZE,
92 WARN_AFTER_CHUNK_GZIP_SIZE
93 );
94 console.log();
96 const appPackage = require(paths.appPackageJson);
97 const publicUrl = paths.publicUrl;
98 const publicPath = config.output.publicPath;
99 const buildFolder = path.relative(process.cwd(), paths.appBuild);
100 printHostingInstructions(
101 appPackage,
102 publicUrl,
103 publicPath,
104 buildFolder,
105 useYarn
106 );
107 },
108 err => {
109 console.log(chalk.red('Failed to compile.\n'));
110 printBuildError(err);
111 process.exit(1);
112 }
113 )
114 .catch(err => {
115 if (err && err.message) {
116 console.log(err.message);
117 }
118 process.exit(1);
119 });
121// Create the production build and print the deployment instructions.
122function build(previousFileSizes) {
123 // We used to support resolving modules according to `NODE_PATH`.
124 // This now has been deprecated in favor of jsconfig/tsconfig.json
125 // This lets you use absolute paths in imports inside large monorepos:
126 if (process.env.NODE_PATH) {
127 console.log(
128 chalk.yellow(
129 'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.'
130 )
131 );
132 console.log();
133 }
135 console.log('Creating an optimized production build...');
137 const compiler = webpack(config);
138 return new Promise((resolve, reject) => {
139 compiler.run((err, stats) => {
140 let messages;
141 if (err) {
142 if (!err.message) {
143 return reject(err);
144 }
145 messages = formatWebpackMessages({
146 errors: [err.message],
147 warnings: [],
148 });
149 } else {
150 messages = formatWebpackMessages(
151 stats.toJson({ all: false, warnings: true, errors: true })
152 );
153 }
154 if (messages.errors.length) {
155 // Only keep the first error. Others are often indicative
156 // of the same problem, but confuse the reader with noise.
157 if (messages.errors.length > 1) {
158 messages.errors.length = 1;
159 }
160 return reject(new Error(messages.errors.join('\n\n')));
161 }
162 if (
163 process.env.CI &&
164 (typeof process.env.CI !== 'string' ||
165 process.env.CI.toLowerCase() !== 'false') &&
166 messages.warnings.length
167 ) {
168 console.log(
169 chalk.yellow(
170 '\nTreating warnings as errors because process.env.CI = true.\n' +
171 'Most CI servers set it automatically.\n'
172 )
173 );
174 return reject(new Error(messages.warnings.join('\n\n')));
175 }
177 return resolve({
178 stats,
179 previousFileSizes,
180 warnings: messages.warnings,
181 });
182 });
183 });
186function copyPublicFolder() {
187 fs.copySync(paths.appPublic, paths.appBuild, {
188 dereference: true,
189 filter: file => file !== paths.appHtml,
190 });