formatWebpackMessages.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /**
  2. * Copyright (c) 2015-present, Facebook, Inc.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. 'use strict';
  8. const friendlySyntaxErrorLabel = 'Syntax error:';
  9. function isLikelyASyntaxError(message) {
  10. return message.indexOf(friendlySyntaxErrorLabel) !== -1;
  11. }
  12. // Cleans up webpack error messages.
  13. function formatMessage(message) {
  14. let lines = message.split('\n');
  15. // Strip webpack-added headers off errors/warnings
  16. // https://github.com/webpack/webpack/blob/master/lib/ModuleError.js
  17. lines = lines.filter(line => !/Module [A-z ]+\(from/.test(line));
  18. // Transform parsing error into syntax error
  19. // TODO: move this to our ESLint formatter?
  20. lines = lines.map(line => {
  21. const parsingError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec(
  22. line
  23. );
  24. if (!parsingError) {
  25. return line;
  26. }
  27. const [, errorLine, errorColumn, errorMessage] = parsingError;
  28. return `${friendlySyntaxErrorLabel} ${errorMessage} (${errorLine}:${errorColumn})`;
  29. });
  30. message = lines.join('\n');
  31. // Smoosh syntax errors (commonly found in CSS)
  32. message = message.replace(
  33. /SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g,
  34. `${friendlySyntaxErrorLabel} $3 ($1:$2)\n`
  35. );
  36. // Clean up export errors
  37. message = message.replace(
  38. /^.*export '(.+?)' was not found in '(.+?)'.*$/gm,
  39. `Attempted import error: '$1' is not exported from '$2'.`
  40. );
  41. message = message.replace(
  42. /^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
  43. `Attempted import error: '$2' does not contain a default export (imported as '$1').`
  44. );
  45. message = message.replace(
  46. /^.*export '(.+?)' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
  47. `Attempted import error: '$1' is not exported from '$3' (imported as '$2').`
  48. );
  49. lines = message.split('\n');
  50. // Remove leading newline
  51. if (lines.length > 2 && lines[1].trim() === '') {
  52. lines.splice(1, 1);
  53. }
  54. // Clean up file name
  55. lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1');
  56. // Cleans up verbose "module not found" messages for files and packages.
  57. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) {
  58. lines = [
  59. lines[0],
  60. lines[1]
  61. .replace('Error: ', '')
  62. .replace('Module not found: Cannot find file:', 'Cannot find file:'),
  63. ];
  64. }
  65. // Add helpful message for users trying to use Sass for the first time
  66. if (lines[1] && lines[1].match(/Cannot find module.+node-sass/)) {
  67. lines[1] = 'To import Sass files, you first need to install node-sass.\n';
  68. lines[1] +=
  69. 'Run `npm install node-sass` or `yarn add node-sass` inside your workspace.';
  70. }
  71. message = lines.join('\n');
  72. // Internal stacks are generally useless so we strip them... with the
  73. // exception of stacks containing `webpack:` because they're normally
  74. // from user code generated by webpack. For more information see
  75. // https://github.com/facebook/create-react-app/pull/1050
  76. message = message.replace(
  77. /^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm,
  78. ''
  79. ); // at ... ...:x:y
  80. message = message.replace(/^\s*at\s<anonymous>(\n|$)/gm, ''); // at <anonymous>
  81. lines = message.split('\n');
  82. // Remove duplicated newlines
  83. lines = lines.filter(
  84. (line, index, arr) =>
  85. index === 0 || line.trim() !== '' || line.trim() !== arr[index - 1].trim()
  86. );
  87. // Reassemble the message
  88. message = lines.join('\n');
  89. return message.trim();
  90. }
  91. function formatWebpackMessages(json) {
  92. const formattedErrors = json.errors.map(formatMessage);
  93. const formattedWarnings = json.warnings.map(formatMessage);
  94. const result = { errors: formattedErrors, warnings: formattedWarnings };
  95. if (result.errors.some(isLikelyASyntaxError)) {
  96. // If there are any syntax errors, show just them.
  97. result.errors = result.errors.filter(isLikelyASyntaxError);
  98. }
  99. return result;
  100. }
  101. module.exports = formatWebpackMessages;