/** * @typedef {Object} WebpackErrorObj * @property {string} moduleIdentifier * @property {string} moduleName * @property {string} message */ const friendlySyntaxErrorLabel = 'Syntax error:'; /** * Checks if the error message is for a syntax error. * @param {string} message The raw Webpack error message. * @returns {boolean} Whether the error message is for a syntax error. */ function isLikelyASyntaxError(message) { return message.indexOf(friendlySyntaxErrorLabel) !== -1; } /** * Cleans up Webpack error messages. * * 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). * @param {string} message The raw Webpack error message. * @returns {string} The formatted Webpack error message. */ function formatMessage(message) { let lines = message.split('\n'); // Strip Webpack-added headers off errors/warnings // https://github.com/webpack/webpack/blob/master/lib/ModuleError.js lines = lines.filter(function (line) { return !/Module [A-z ]+\(from/.test(line); }); // Remove leading newline if (lines.length > 2 && lines[1].trim() === '') { lines.splice(1, 1); } // Remove duplicated newlines lines = lines.filter(function (line, index, arr) { return index === 0 || line.trim() !== '' || line.trim() !== arr[index - 1].trim(); }); // Clean up the file name lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1'); // Cleans up verbose "module not found" messages for files and packages. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) { lines = [ lines[0], lines[1] .replace('Error: ', '') .replace('Module not found: Cannot find file:', 'Cannot find file:'), ]; } message = lines.join('\n'); // Clean up syntax errors message = message.replace('SyntaxError:', friendlySyntaxErrorLabel); // Internal stacks are generally useless, so we strip them - // except the stacks containing `webpack:`, // because they're normally from user code generated by webpack. message = message.replace(/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, ''); // at ... ...:x:y message = message.replace(/^\s*at\s((?!webpack:).)*[\s)]*(\n|$)/gm, ''); // at ... message = message.replace(/^\s*at\s(\n|$)/gm, ''); // at return message.trim(); } /** * Formats Webpack error messages into a more readable format. * @param {Array} errors An array of Webpack error messages. * @returns {string[]} The formatted Webpack error messages. */ function formatWebpackErrors(errors) { let formattedErrors = errors.map(function (errorObjOrMessage) { // Webpack 5 compilation errors are in the form of descriptor objects, // so we have to join pieces to get the format we want. if (typeof errorObjOrMessage === 'object') { return formatMessage([errorObjOrMessage.moduleName, errorObjOrMessage.message].join('\n')); } // Webpack 4 compilation errors are strings return formatMessage(errorObjOrMessage); }); if (formattedErrors.some(isLikelyASyntaxError)) { // If there are any syntax errors, show just them. formattedErrors = formattedErrors.filter(isLikelyASyntaxError); } return formattedErrors; } module.exports = formatWebpackErrors;