Skip to content

Commit 8f68852

Browse files
committed
Identify and group ModuleNotFound errors
As suggested in facebook/create-react-app#401
1 parent 1b22671 commit 8f68852

File tree

2 files changed

+52
-22
lines changed

2 files changed

+52
-22
lines changed

lib/webpack/plugins/formatMessage.js

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,53 @@ function cleanStackTrace (message) {
77
}
88

99
function isBabelSyntaxError (e) {
10-
// ModuleNotFoundError
11-
// ModuleBuildError
1210
return e.name === 'ModuleBuildError' && e.message.indexOf('SyntaxError') >= 0;
1311
}
1412

13+
function isModuleNotFoundError (e) {
14+
return e.name === 'ModuleNotFoundError'
15+
&& e.message.indexOf('Module not found') === 0
16+
&& e.dependencies && e.dependencies.length;
17+
}
18+
1519
function formatMessage (webpackError) {
1620

1721
const error = extractError(webpackError);
1822
if (isBabelSyntaxError(webpackError)) {
1923
error.message = cleanStackTrace(error.message + '\n');
24+
error.type = 'babel-syntax-error';
25+
error.severity = 1000;
26+
} else if (isModuleNotFoundError(webpackError)) {
27+
error.message = `Module not found ${webpackError.dependencies[0].request}`;
28+
error.module = webpackError.dependencies[0].request;
29+
error.type = 'module-not-found';
30+
error.severity = 900;
31+
} else {
32+
error.severity = 0;
2033
}
2134

2235
return error;
2336
}
2437

2538
function extractError (e) {
26-
if (typeof e === "string") {
27-
return {
28-
message: e
29-
};
30-
}
39+
return {
40+
message: e.message,
41+
file: getFile(e),
42+
origin: getOrigin(e),
43+
name: e.name
44+
};
45+
}
3146

32-
// if (e.chunk) {
33-
// text += "chunk " + (e.chunk.name || e.chunk.id) +
34-
// (e.chunk.hasRuntime() ? " [entry]" : e.chunk.isInitial() ? " [initial]" : "") + "\n";
35-
// }
36-
let file = null;
47+
48+
function getFile (e) {
3749
if (e.file) {
38-
file = e.file;
50+
return e.file;
3951
} else if (e.module && e.module.readableIdentifier && typeof e.module.readableIdentifier === "function") {
40-
file = e.module.readableIdentifier(requestShortener);
52+
return e.module.readableIdentifier(requestShortener);
4153
}
54+
}
4255

56+
function getOrigin (e) {
4357
let origin = '';
4458
if (e.dependencies && e.origin) {
4559
origin += '\n @ ' + e.origin.readableIdentifier(requestShortener);
@@ -57,13 +71,7 @@ function extractError (e) {
5771
origin += '\n @ ' + current.readableIdentifier(requestShortener);
5872
}
5973
}
60-
61-
return {
62-
message: e.message,
63-
file,
64-
origin,
65-
name: e.name
66-
};
74+
return origin;
6775
}
6876

6977
module.exports = formatMessage;

lib/webpack/plugins/notifier.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,18 @@ class NotifierPlugin {
5353
if (this.notifier) {
5454
this.notify('Error', formattedErrors[0]);
5555
}
56-
formattedErrors.forEach((error, index) => displayError(index, 'Error', error));
56+
57+
formattedErrors = getMaxSeverityErrors(formattedErrors, 'severity');
58+
if (formattedErrors[0].type === 'module-not-found') {
59+
console.log('These dependencies were not found in node_modules:');
60+
console.log();
61+
formattedErrors.forEach((error, index) => console.log('*', error.module));
62+
console.log();
63+
console.log('Did you forget to run npm install --save for them?')
64+
} else {
65+
formattedErrors.forEach((error, index) => displayError(index, 'Error', error));
66+
}
67+
5768
return;
5869
}
5970

@@ -73,6 +84,17 @@ class NotifierPlugin {
7384
}
7485
}
7586

87+
function getMaxSeverityErrors (errors) {
88+
const maxSeverity = getMaxInt(errors, 'severity');
89+
return errors.filter(e => e.severity === maxSeverity);
90+
}
91+
92+
function getMaxInt(collection, propertyName) {
93+
return collection.reduce((res, curr) => {
94+
return curr[propertyName] > res ? curr[propertyName] : res;
95+
}, 0)
96+
}
97+
7698
module.exports = NotifierPlugin;
7799

78100
function displayError (index, severity, error) {

0 commit comments

Comments
 (0)