formatWebpackErrors.js 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**
  2. * @typedef {Object} WebpackErrorObj
  3. * @property {string} moduleIdentifier
  4. * @property {string} moduleName
  5. * @property {string} message
  6. */
  7. const friendlySyntaxErrorLabel = 'Syntax error:';
  8. /**
  9. * Checks if the error message is for a syntax error.
  10. * @param {string} message The raw Webpack error message.
  11. * @returns {boolean} Whether the error message is for a syntax error.
  12. */
  13. function isLikelyASyntaxError(message) {
  14. return message.indexOf(friendlySyntaxErrorLabel) !== -1;
  15. }
  16. /**
  17. * Cleans up Webpack error messages.
  18. *
  19. * This implementation is based on the one from [create-react-app](https://github.com/facebook/create-react-app/blob/edc671eeea6b7d26ac3f1eb2050e50f75cf9ad5d/packages/react-dev-utils/formatWebpackMessages.js).
  20. * @param {string} message The raw Webpack error message.
  21. * @returns {string} The formatted Webpack error message.
  22. */
  23. function formatMessage(message) {
  24. let lines = message.split('\n');
  25. // Strip Webpack-added headers off errors/warnings
  26. // https://github.com/webpack/webpack/blob/master/lib/ModuleError.js
  27. lines = lines.filter(function (line) {
  28. return !/Module [A-z ]+\(from/.test(line);
  29. });
  30. // Remove leading newline
  31. if (lines.length > 2 && lines[1].trim() === '') {
  32. lines.splice(1, 1);
  33. }
  34. // Remove duplicated newlines
  35. lines = lines.filter(function (line, index, arr) {
  36. return index === 0 || line.trim() !== '' || line.trim() !== arr[index - 1].trim();
  37. });
  38. // Clean up the file name
  39. lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1');
  40. // Cleans up verbose "module not found" messages for files and packages.
  41. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) {
  42. lines = [
  43. lines[0],
  44. lines[1]
  45. .replace('Error: ', '')
  46. .replace('Module not found: Cannot find file:', 'Cannot find file:'),
  47. ];
  48. }
  49. message = lines.join('\n');
  50. // Clean up syntax errors
  51. message = message.replace('SyntaxError:', friendlySyntaxErrorLabel);
  52. // Internal stacks are generally useless, so we strip them -
  53. // except the stacks containing `webpack:`,
  54. // because they're normally from user code generated by webpack.
  55. message = message.replace(/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, ''); // at ... ...:x:y
  56. message = message.replace(/^\s*at\s((?!webpack:).)*<anonymous>[\s)]*(\n|$)/gm, ''); // at ... <anonymous>
  57. message = message.replace(/^\s*at\s<anonymous>(\n|$)/gm, ''); // at <anonymous>
  58. return message.trim();
  59. }
  60. /**
  61. * Formats Webpack error messages into a more readable format.
  62. * @param {Array<string | WebpackErrorObj>} errors An array of Webpack error messages.
  63. * @returns {string[]} The formatted Webpack error messages.
  64. */
  65. function formatWebpackErrors(errors) {
  66. let formattedErrors = errors.map(function (errorObjOrMessage) {
  67. // Webpack 5 compilation errors are in the form of descriptor objects,
  68. // so we have to join pieces to get the format we want.
  69. if (typeof errorObjOrMessage === 'object') {
  70. return formatMessage([errorObjOrMessage.moduleName, errorObjOrMessage.message].join('\n'));
  71. }
  72. // Webpack 4 compilation errors are strings
  73. return formatMessage(errorObjOrMessage);
  74. });
  75. if (formattedErrors.some(isLikelyASyntaxError)) {
  76. // If there are any syntax errors, show just them.
  77. formattedErrors = formattedErrors.filter(isLikelyASyntaxError);
  78. }
  79. return formattedErrors;
  80. }
  81. module.exports = formatWebpackErrors;