UNPKG

5.15 kBJavaScriptView Raw
1// @remove-on-eject-begin
2/**
3 * Copyright (c) 2015-present, Facebook, Inc.
4 *
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8// @remove-on-eject-end
9'use strict';
10
11// Do this as the first thing so that any code reading it knows the right env.
12process.env.BABEL_ENV = 'production';
13process.env.NODE_ENV = 'production';
14
15// Makes the script crash on unhandled rejections instead of silently
16// ignoring them. In the future, promise rejections that are not handled will
17// terminate the Node.js process with a non-zero exit code.
18process.on('unhandledRejection', err => {
19 throw err;
20});
21
22// Ensure environment variables are read.
23require('../config/env');
24
25const path = require('path');
26const chalk = require('chalk');
27const fs = require('fs-extra');
28const webpack = require('webpack');
29const config = require('../config/webpack.config.prod');
30const paths = require('../config/paths');
31const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
32const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
33const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
34const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
35const printBuildError = require('react-dev-utils/printBuildError');
36
37const measureFileSizesBeforeBuild =
38 FileSizeReporter.measureFileSizesBeforeBuild;
39const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
40const useYarn = fs.existsSync(paths.yarnLockFile);
41
42// These sizes are pretty large. We'll warn for bundles exceeding them.
43const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
44const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
45
46// Warn and crash if required files are missing
47if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
48 process.exit(1);
49}
50
51// First, read the current file sizes in build directory.
52// This lets us display how much they changed later.
53measureFileSizesBeforeBuild(paths.appBuild)
54 .then(previousFileSizes => {
55 // Remove all content but keep the directory so that
56 // if you're in it, you don't end up in Trash
57 fs.emptyDirSync(paths.appBuild);
58 // Merge with the public folder
59 copyPublicFolder();
60 // Start the webpack build
61 return build(previousFileSizes);
62 })
63 .then(
64 ({ stats, previousFileSizes, warnings }) => {
65 if (warnings.length) {
66 console.log(chalk.yellow('Compiled with warnings.\n'));
67 console.log(warnings.join('\n\n'));
68 console.log(
69 '\nSearch for the ' +
70 chalk.underline(chalk.yellow('keywords')) +
71 ' to learn more about each warning.'
72 );
73 console.log(
74 'To ignore, add ' +
75 chalk.cyan('// eslint-disable-next-line') +
76 ' to the line before.\n'
77 );
78 } else {
79 console.log(chalk.green('Compiled successfully.\n'));
80 }
81
82 console.log('File sizes after gzip:\n');
83 printFileSizesAfterBuild(
84 stats,
85 previousFileSizes,
86 paths.appBuild,
87 WARN_AFTER_BUNDLE_GZIP_SIZE,
88 WARN_AFTER_CHUNK_GZIP_SIZE
89 );
90 console.log();
91
92 const appPackage = require(paths.appPackageJson);
93 const publicUrl = paths.publicUrl;
94 const publicPath = config.output.publicPath;
95 const buildFolder = path.relative(process.cwd(), paths.appBuild);
96 printHostingInstructions(
97 appPackage,
98 publicUrl,
99 publicPath,
100 buildFolder,
101 useYarn
102 );
103 },
104 err => {
105 console.log(chalk.red('Failed to compile.\n'));
106 printBuildError(err);
107 process.exit(1);
108 }
109 );
110
111// Create the production build and print the deployment instructions.
112function build(previousFileSizes) {
113 console.log('Creating an optimized production build...');
114
115 let compiler = webpack(config);
116 return new Promise((resolve, reject) => {
117 compiler.run((err, stats) => {
118 if (err) {
119 return reject(err);
120 }
121 const messages = formatWebpackMessages(stats.toJson({}, true));
122 if (messages.errors.length) {
123 // Only keep the first error. Others are often indicative
124 // of the same problem, but confuse the reader with noise.
125 if (messages.errors.length > 1) {
126 messages.errors.length = 1;
127 }
128 return reject(new Error(messages.errors.join('\n\n')));
129 }
130 if (
131 process.env.CI &&
132 (typeof process.env.CI !== 'string' ||
133 process.env.CI.toLowerCase() !== 'false') &&
134 messages.warnings.length
135 ) {
136 console.log(
137 chalk.yellow(
138 '\nTreating warnings as errors because process.env.CI = true.\n' +
139 'Most CI servers set it automatically.\n'
140 )
141 );
142 return reject(new Error(messages.warnings.join('\n\n')));
143 }
144 return resolve({
145 stats,
146 previousFileSizes,
147 warnings: messages.warnings,
148 });
149 });
150 });
151}
152
153function copyPublicFolder() {
154 fs.copySync(paths.appPublic, paths.appBuild, {
155 dereference: true,
156 filter: file => file !== paths.appHtml,
157 });
158}