Skip to content

Commit 38f92c3

Browse files
authored
Merge pull request #374 from fs-webdev/betterErrorLogging
better error handling/logging for failed builds
2 parents b91433b + f772be3 commit 38f92c3

File tree

4 files changed

+119
-101
lines changed

4 files changed

+119
-101
lines changed

CHANGELOG-FRONTIER.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 8.8.1
2+
3+
- Wrap the index-revision-replace code in a try/catch. Log the error message in the catch, but DON'T throw the error.
4+
- By not throwing the error in the plugin, the already existing error logging will log the underlying issues as expected
5+
- add, (and commented out) a tap into afterCompile hook to check if errors exist. If so, then log those full error objects
6+
17
## 8.8.0
28

39
- Removed some proxies that are no longer needed, and scoped some others tighter to not conflict with localhost URLs

packages/react-scripts/config/index-revision-replace.js

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
1-
"use strict"
1+
'use strict'
22

33
const fs = require('fs')
44
const path = require('path')
5-
const { createHash } = require('crypto');
5+
const { createHash } = require('crypto')
66

77
class IndexRevision {
8-
98
apply(compiler) {
109
compiler.hooks.done.tap('IndexRevisionReplace', () => {
1110
const builtServiceWorkerPath = path.resolve('build/service-worker.js')
1211
const _indexHtmlPath = path.resolve('build/_index.html')
1312

14-
const _indexSrcCode = fs.readFileSync(_indexHtmlPath, 'utf-8')
15-
const _indexHashRaw = md5(_indexSrcCode)
16-
const _indexHashAsString = `"${_indexHashRaw}"`
17-
18-
let serviceWorkerCode = fs.readFileSync(builtServiceWorkerPath, 'utf-8')
19-
serviceWorkerCode = serviceWorkerCode.replace('self._INDEX_HASH', _indexHashAsString)
20-
21-
fs.writeFileSync(builtServiceWorkerPath, serviceWorkerCode)
13+
try {
14+
const _indexSrcCode = fs.readFileSync(_indexHtmlPath, 'utf-8')
15+
const _indexHashRaw = md5(_indexSrcCode)
16+
const _indexHashAsString = `"${_indexHashRaw}"`
17+
18+
let serviceWorkerCode = fs.readFileSync(builtServiceWorkerPath, 'utf-8')
19+
serviceWorkerCode = serviceWorkerCode.replace('self._INDEX_HASH', _indexHashAsString)
20+
21+
fs.writeFileSync(builtServiceWorkerPath, serviceWorkerCode)
22+
} catch (error) {
23+
console.log(
24+
`Failure in index-revision-replace.js. Almost always this is because of another failure in compilation.
25+
Look for and fix other errors before addressing _index.html not found:`,
26+
error.message,
27+
'\n'
28+
)
29+
}
2230
})
2331
}
24-
2532
}
2633

2734
function md5(input) {

packages/react-scripts/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fs/react-scripts",
3-
"version": "8.8.0",
3+
"version": "8.8.1",
44
"upstreamVersion": "5.0.1",
55
"description": "Configuration and scripts for Create React App.",
66
"repository": {

packages/react-scripts/scripts/build.js

Lines changed: 93 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,178 +6,183 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88
// @remove-on-eject-end
9-
'use strict';
9+
'use strict'
1010

1111
// Do this as the first thing so that any code reading it knows the right env.
12-
process.env.BABEL_ENV = 'production';
13-
process.env.NODE_ENV = 'production';
12+
process.env.BABEL_ENV = 'production'
13+
process.env.NODE_ENV = 'production'
1414

1515
// Makes the script crash on unhandled rejections instead of silently
1616
// ignoring them. In the future, promise rejections that are not handled will
1717
// terminate the Node.js process with a non-zero exit code.
1818
process.on('unhandledRejection', err => {
19-
throw err;
20-
});
19+
throw err
20+
})
2121

2222
// Ensure environment variables are read.
23-
require('../config/env');
24-
25-
const path = require('path');
26-
const chalk = require('react-dev-utils/chalk');
27-
const fs = require('fs-extra');
28-
const bfj = require('bfj');
29-
const webpack = require('webpack');
30-
const configFactory = require('../config/webpack.config');
31-
const paths = require('../config/paths');
32-
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
33-
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
34-
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
35-
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
36-
const printBuildError = require('react-dev-utils/printBuildError');
23+
require('../config/env')
24+
25+
const path = require('path')
26+
const chalk = require('react-dev-utils/chalk')
27+
const fs = require('fs-extra')
28+
const bfj = require('bfj')
29+
const webpack = require('webpack')
30+
const configFactory = require('../config/webpack.config')
31+
const paths = require('../config/paths')
32+
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles')
33+
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages')
34+
const printHostingInstructions = require('react-dev-utils/printHostingInstructions')
35+
const FileSizeReporter = require('react-dev-utils/FileSizeReporter')
36+
const printBuildError = require('react-dev-utils/printBuildError')
3737
// frontier
3838
// coalesce per-locale locales for speedier intl perf scaling
39-
const { coalesceLocales } = require('./coalesceLocales');
39+
const { coalesceLocales } = require('./coalesceLocales')
4040
// /frontier
4141

42-
const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild;
43-
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
44-
const useYarn = fs.existsSync(paths.yarnLockFile);
42+
const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild
43+
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild
44+
const useYarn = fs.existsSync(paths.yarnLockFile)
4545

4646
// These sizes are pretty large. We'll warn for bundles exceeding them.
47-
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
48-
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
47+
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024
48+
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024
4949

50-
const isInteractive = process.stdout.isTTY;
50+
const isInteractive = process.stdout.isTTY
5151

5252
// Warn and crash if required files are missing
5353
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
54-
process.exit(1);
54+
process.exit(1)
5555
}
5656

57-
const argv = process.argv.slice(2);
58-
const writeStatsJson = argv.indexOf('--stats') !== -1;
57+
const argv = process.argv.slice(2)
58+
const writeStatsJson = argv.indexOf('--stats') !== -1
5959

6060
// Generate configuration
61-
const config = configFactory('production');
61+
const config = configFactory('production')
6262

6363
// We require that you explicitly set browsers and do not fall back to
6464
// browserslist defaults.
65-
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
65+
const { checkBrowsers } = require('react-dev-utils/browsersHelper')
6666
checkBrowsers(paths.appPath, isInteractive)
6767
.then(() => {
6868
// First, read the current file sizes in build directory.
6969
// This lets us display how much they changed later.
70-
return measureFileSizesBeforeBuild(paths.appBuild);
70+
return measureFileSizesBeforeBuild(paths.appBuild)
7171
})
7272
.then(previousFileSizes => {
7373
// Remove all content but keep the directory so that
7474
// if you're in it, you don't end up in Trash
75-
fs.emptyDirSync(paths.appBuild);
75+
fs.emptyDirSync(paths.appBuild)
7676
// Merge with the public folder
77-
copyPublicFolder();
77+
copyPublicFolder()
7878
// Start the webpack build
79-
return build(previousFileSizes);
79+
return build(previousFileSizes)
8080
})
8181
.then(
8282
({ stats, previousFileSizes, warnings }) => {
8383
if (warnings.length) {
84-
console.log(chalk.yellow('Compiled with warnings.\n'));
85-
console.log(warnings.join('\n\n'));
84+
console.log(chalk.yellow('Compiled with warnings.\n'))
85+
console.log(warnings.join('\n\n'))
8686
console.log(
87-
'\nSearch for the ' +
88-
chalk.underline(chalk.yellow('keywords')) +
89-
' to learn more about each warning.'
90-
);
91-
console.log(
92-
'To ignore, add ' + chalk.cyan('// eslint-disable-next-line') + ' to the line before.\n'
93-
);
87+
'\nSearch for the ' + chalk.underline(chalk.yellow('keywords')) + ' to learn more about each warning.'
88+
)
89+
console.log('To ignore, add ' + chalk.cyan('// eslint-disable-next-line') + ' to the line before.\n')
9490
} else {
95-
console.log(chalk.green('Compiled successfully.\n'));
91+
console.log(chalk.green('Compiled successfully.\n'))
9692
}
9793

98-
console.log('File sizes after gzip:\n');
94+
console.log('File sizes after gzip:\n')
9995
printFileSizesAfterBuild(
10096
stats,
10197
previousFileSizes,
10298
paths.appBuild,
10399
WARN_AFTER_BUNDLE_GZIP_SIZE,
104100
WARN_AFTER_CHUNK_GZIP_SIZE
105-
);
106-
console.log();
107-
108-
const appPackage = require(paths.appPackageJson);
109-
const publicUrl = paths.publicUrlOrPath;
110-
const publicPath = config.output.publicPath;
111-
const buildFolder = path.relative(process.cwd(), paths.appBuild);
112-
printHostingInstructions(appPackage, publicUrl, publicPath, buildFolder, useYarn);
101+
)
102+
console.log()
103+
104+
const appPackage = require(paths.appPackageJson)
105+
const publicUrl = paths.publicUrlOrPath
106+
const publicPath = config.output.publicPath
107+
const buildFolder = path.relative(process.cwd(), paths.appBuild)
108+
printHostingInstructions(appPackage, publicUrl, publicPath, buildFolder, useYarn)
113109
},
114110
err => {
115-
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
111+
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'
116112
if (tscCompileOnError) {
117113
console.log(
118114
chalk.yellow(
119115
'Compiled with the following type errors (you may want to check these before deploying your app):\n'
120116
)
121-
);
122-
printBuildError(err);
117+
)
118+
printBuildError(err)
123119
} else {
124-
console.log(chalk.red('Failed to compile.\n'));
125-
printBuildError(err);
126-
process.exit(1);
120+
console.log(chalk.red('Failed to compile.\n'))
121+
printBuildError(err)
122+
process.exit(1)
127123
}
128124
}
129125
)
130126
.catch(err => {
131127
if (err && err.message) {
132-
console.log(err.message);
128+
console.log(err.message)
133129
}
134-
process.exit(1);
135-
});
130+
process.exit(1)
131+
})
136132

137133
// Create the production build and print the deployment instructions.
138134
function build(previousFileSizes) {
139-
console.log('Creating an optimized production build...');
135+
console.log('Creating an optimized production build...')
140136

141-
const compiler = webpack(config);
137+
const compiler = webpack(config)
142138
return new Promise((resolve, reject) => {
143139
// frontier
144140
// coalesce per-locale locales for speedier intl perf scaling
145141
compiler.hooks.beforeRun.tap('perlocale', () => {
146-
coalesceLocales(paths);
147-
});
142+
coalesceLocales(paths)
143+
})
144+
145+
// UNCOMMENT FOR MORE DETAILS OF THE ERRORS IN A BUILD
146+
// compiler.hooks.afterCompile.tap('afterCompile', compilation => {
147+
// if (compilation.errors && compilation.errors.length > 0) {
148+
// console.log(
149+
// chalk.red(
150+
// 'Errors occurred during compilation. Try to resolve the problems, and reach out to the Frontier Core team if you need help:\n'
151+
// ),
152+
// compilation.errors
153+
// )
154+
// }
155+
// })
156+
148157
// /frontier
149158
compiler.run((err, stats) => {
150-
let messages;
159+
let messages
151160
if (err) {
152161
if (!err.message) {
153-
return reject(err);
162+
return reject(err)
154163
}
155164

156-
let errMessage = err.message;
165+
let errMessage = err.message
157166

158167
// Add additional information for postcss errors
159168
if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) {
160-
errMessage +=
161-
'\nCompileError: Begins at CSS selector ' +
162-
err['postcssNode'].selector;
169+
errMessage += '\nCompileError: Begins at CSS selector ' + err['postcssNode'].selector
163170
}
164171

165172
messages = formatWebpackMessages({
166173
errors: [errMessage],
167174
warnings: [],
168-
});
175+
})
169176
} else {
170-
messages = formatWebpackMessages(
171-
stats.toJson({ all: false, warnings: true, errors: true })
172-
);
177+
messages = formatWebpackMessages(stats.toJson({ all: false, warnings: true, errors: true }))
173178
}
174179
if (messages.errors.length) {
175180
// Only keep the first error. Others are often indicative
176181
// of the same problem, but confuse the reader with noise.
177182
if (messages.errors.length > 1) {
178-
messages.errors.length = 1;
183+
messages.errors.length = 1
179184
}
180-
return reject(new Error(messages.errors.join('\n\n')));
185+
return reject(new Error(messages.errors.join('\n\n')))
181186
}
182187
if (
183188
process.env.CI &&
@@ -188,39 +193,39 @@ function build(previousFileSizes) {
188193
// Frontier Ignore eslint warnings as well
189194
const filteredWarnings = messages.warnings.filter(
190195
w => !/Failed to parse source map/.test(w) && !/\[eslint\]/.test(w)
191-
);
196+
)
192197
if (filteredWarnings.length) {
193198
console.log(
194199
chalk.yellow(
195200
'\nTreating warnings as errors because process.env.CI = true.\n' +
196201
'Most CI servers set it automatically.\n'
197202
)
198-
);
199-
return reject(new Error(filteredWarnings.join('\n\n')));
203+
)
204+
return reject(new Error(filteredWarnings.join('\n\n')))
200205
}
201206
}
202207

203208
const resolveArgs = {
204209
stats,
205210
previousFileSizes,
206211
warnings: messages.warnings,
207-
};
212+
}
208213

209214
if (writeStatsJson) {
210215
return bfj
211216
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
212217
.then(() => resolve(resolveArgs))
213-
.catch(error => reject(new Error(error)));
218+
.catch(error => reject(new Error(error)))
214219
}
215220

216-
return resolve(resolveArgs);
217-
});
218-
});
221+
return resolve(resolveArgs)
222+
})
223+
})
219224
}
220225

221226
function copyPublicFolder() {
222227
fs.copySync(paths.appPublic, paths.appBuild, {
223228
dereference: true,
224229
filter: file => file !== paths.appHtml,
225-
});
230+
})
226231
}

0 commit comments

Comments
 (0)