Skip to content

Commit bacbf59

Browse files
authored
Refactor and improve build output (facebook#2202)
1 parent 0cb605e commit bacbf59

File tree

1 file changed

+58
-142
lines changed

1 file changed

+58
-142
lines changed

scripts/build.js

+58-142
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ process.on('unhandledRejection', err => {
2323
// Ensure environment variables are read.
2424
require('../config/env');
2525

26+
const path = require('path');
2627
const chalk = require('chalk');
2728
const fs = require('fs-extra');
28-
const path = require('path');
29-
const url = require('url');
3029
const webpack = require('webpack');
3130
const config = require('../config/webpack.config.prod');
3231
const paths = require('../config/paths');
3332
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
33+
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
34+
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
3435
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
3536

3637
const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild;
@@ -44,159 +45,74 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
4445

4546
// First, read the current file sizes in build directory.
4647
// This lets us display how much they changed later.
47-
measureFileSizesBeforeBuild(paths.appBuild).then(previousFileSizes => {
48-
// Remove all content but keep the directory so that
49-
// if you're in it, you don't end up in Trash
50-
fs.emptyDirSync(paths.appBuild);
51-
52-
// Start the webpack build
53-
build(previousFileSizes);
54-
55-
// Merge with the public folder
56-
copyPublicFolder();
57-
});
58-
59-
// Print out errors
60-
function printErrors(summary, errors) {
61-
console.log(chalk.red(summary));
62-
console.log();
63-
errors.forEach(err => {
64-
console.log(err.message || err);
65-
console.log();
66-
});
67-
}
68-
69-
// Create the production build and print the deployment instructions.
70-
function build(previousFileSizes) {
71-
console.log('Creating an optimized production build...');
72-
73-
let compiler;
74-
try {
75-
compiler = webpack(config);
76-
} catch (err) {
77-
printErrors('Failed to compile.', [err]);
78-
process.exit(1);
79-
}
80-
81-
compiler.run((err, stats) => {
82-
if (err) {
83-
printErrors('Failed to compile.', [err]);
84-
process.exit(1);
85-
}
48+
measureFileSizesBeforeBuild(paths.appBuild)
49+
.then(previousFileSizes => {
50+
// Remove all content but keep the directory so that
51+
// if you're in it, you don't end up in Trash
52+
fs.emptyDirSync(paths.appBuild);
53+
// Merge with the public folder
54+
copyPublicFolder();
55+
// Start the webpack build
56+
return build(previousFileSizes);
57+
})
58+
.then(
59+
({ stats, previousFileSizes }) => {
60+
console.log(chalk.green('Compiled successfully.'));
61+
console.log();
8662

87-
if (stats.compilation.errors.length) {
88-
printErrors('Failed to compile.', stats.compilation.errors);
89-
process.exit(1);
90-
}
63+
console.log('File sizes after gzip:');
64+
console.log();
65+
printFileSizesAfterBuild(stats, previousFileSizes);
66+
console.log();
9167

92-
if (process.env.CI && stats.compilation.warnings.length) {
93-
printErrors(
94-
'Failed to compile. When process.env.CI = true, warnings are treated as failures. Most CI servers set this automatically.',
95-
stats.compilation.warnings
68+
const appPackage = require(paths.appPackageJson);
69+
const publicUrl = paths.publicUrl;
70+
const publicPath = config.output.publicPath;
71+
const buildFolder = path.relative(process.cwd(), paths.appBuild);
72+
printHostingInstructions(
73+
appPackage,
74+
publicUrl,
75+
publicPath,
76+
buildFolder,
77+
useYarn
9678
);
79+
},
80+
err => {
81+
console.log(chalk.red('Failed to compile.'));
82+
console.log();
83+
console.log(err.message || err);
84+
console.log();
9785
process.exit(1);
9886
}
87+
);
9988

100-
console.log(chalk.green('Compiled successfully.'));
101-
console.log();
102-
103-
console.log('File sizes after gzip:');
104-
console.log();
105-
printFileSizesAfterBuild(stats, previousFileSizes);
106-
console.log();
89+
// Create the production build and print the deployment instructions.
90+
function build(previousFileSizes) {
91+
console.log('Creating an optimized production build...');
10792

108-
const appPackage = require(paths.appPackageJson);
109-
const publicUrl = paths.publicUrl;
110-
const publicPath = config.output.publicPath;
111-
const publicPathname = url.parse(publicPath).pathname;
112-
if (publicUrl && publicUrl.indexOf('.github.io/') !== -1) {
113-
// "homepage": "http://user.github.io/project"
114-
console.log(
115-
`The project was built assuming it is hosted at ${chalk.green(publicPathname)}.`
116-
);
117-
console.log(
118-
`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`
119-
);
120-
console.log();
121-
console.log(`The ${chalk.cyan('build')} folder is ready to be deployed.`);
122-
console.log(`To publish it at ${chalk.green(publicUrl)}, run:`);
123-
// If script deploy has been added to package.json, skip the instructions
124-
if (typeof appPackage.scripts.deploy === 'undefined') {
125-
console.log();
126-
if (useYarn) {
127-
console.log(` ${chalk.cyan('yarn')} add --dev gh-pages`);
128-
} else {
129-
console.log(` ${chalk.cyan('npm')} install --save-dev gh-pages`);
130-
}
131-
console.log();
132-
console.log(
133-
`Add the following script in your ${chalk.cyan('package.json')}.`
134-
);
135-
console.log();
136-
console.log(` ${chalk.dim('// ...')}`);
137-
console.log(` ${chalk.yellow('"scripts"')}: {`);
138-
console.log(` ${chalk.dim('// ...')}`);
139-
console.log(
140-
` ${chalk.yellow('"predeploy"')}: ${chalk.yellow('"npm run build",')}`
141-
);
142-
console.log(
143-
` ${chalk.yellow('"deploy"')}: ${chalk.yellow('"gh-pages -d build"')}`
144-
);
145-
console.log(' }');
146-
console.log();
147-
console.log('Then run:');
93+
let compiler = webpack(config);
94+
return new Promise((resolve, reject) => {
95+
compiler.run((err, stats) => {
96+
if (err) {
97+
return reject(err);
14898
}
149-
console.log();
150-
console.log(` ${chalk.cyan(useYarn ? 'yarn' : 'npm')} run deploy`);
151-
console.log();
152-
} else if (publicPath !== '/') {
153-
// "homepage": "http://mywebsite.com/project"
154-
console.log(
155-
`The project was built assuming it is hosted at ${chalk.green(publicPath)}.`
156-
);
157-
console.log(
158-
`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`
159-
);
160-
console.log();
161-
console.log(`The ${chalk.cyan('build')} folder is ready to be deployed.`);
162-
console.log();
163-
} else {
164-
if (publicUrl) {
165-
// "homepage": "http://mywebsite.com"
166-
console.log(
167-
`The project was built assuming it is hosted at ${chalk.green(publicUrl)}.`
168-
);
169-
console.log(
170-
`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`
171-
);
172-
console.log();
173-
} else {
174-
// no homepage
175-
console.log(
176-
'The project was built assuming it is hosted at the server root.'
177-
);
178-
console.log(
179-
`To override this, specify the ${chalk.green('homepage')} in your ${chalk.cyan('package.json')}.`
180-
);
181-
console.log('For example, add this to build it for GitHub Pages:');
99+
const messages = formatWebpackMessages(stats.toJson({}, true));
100+
if (messages.errors.length) {
101+
return reject(new Error(messages.errors.join('\n\n')));
102+
}
103+
if (process.env.CI && messages.warnings.length) {
182104
console.log();
183105
console.log(
184-
` ${chalk.green('"homepage"')} ${chalk.cyan(':')} ${chalk.green('"http://myname.github.io/myapp"')}${chalk.cyan(',')}`
106+
chalk.yellow(
107+
'Treating warnings as errors because process.env.CI = true.\n' +
108+
'Most CI servers set it automatically.'
109+
)
185110
);
186111
console.log();
112+
return reject(new Error(messages.warnings.join('\n\n')));
187113
}
188-
const build = path.relative(process.cwd(), paths.appBuild);
189-
console.log(`The ${chalk.cyan(build)} folder is ready to be deployed.`);
190-
console.log('You may serve it with a static server:');
191-
console.log();
192-
if (useYarn) {
193-
console.log(` ${chalk.cyan('yarn')} global add serve`);
194-
} else {
195-
console.log(` ${chalk.cyan('npm')} install -g serve`);
196-
}
197-
console.log(` ${chalk.cyan('serve')} -s build`);
198-
console.log();
199-
}
114+
return resolve({ stats, previousFileSizes });
115+
});
200116
});
201117
}
202118

0 commit comments

Comments
 (0)