From b78547a36609a47db54b814c2e740e40c29e13a8 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Thu, 9 Dec 2021 16:27:51 +0530 Subject: [PATCH 1/4] feat: improve error and warning messages in overlay --- client-src/overlay.js | 9 +- client-src/utils/format-webpack-message.js | 132 ++++++++++++++++++ .../overlay.test.js.snap.webpack5 | 16 +-- 3 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 client-src/utils/format-webpack-message.js diff --git a/client-src/overlay.js b/client-src/overlay.js index 5c074702ff..1edbb781e0 100644 --- a/client-src/overlay.js +++ b/client-src/overlay.js @@ -3,6 +3,7 @@ import ansiHTML from "ansi-html-community"; import { encode } from "html-entities"; +import formatWebpackMessage from "./utils/format-webpack-message.js"; const colors = { reset: ["transparent", "transparent"], @@ -147,11 +148,8 @@ function hide() { */ function formatProblem(type, item) { let header = type === "warning" ? "WARNING" : "ERROR"; - let body = ""; - if (typeof item === "string") { - body += item; - } else { + if (typeof item === "object") { const file = item.file || ""; // eslint-disable-next-line no-nested-ternary const moduleName = item.moduleName @@ -168,10 +166,9 @@ function formatProblem(type, item) { }${loc ? ` ${loc}` : ""}` : "" }`; - body += item.message || ""; } - return { header, body }; + return { header, body: formatWebpackMessage(item) }; } // Compilation with errors (e.g. syntax error or missing modules). diff --git a/client-src/utils/format-webpack-message.js b/client-src/utils/format-webpack-message.js new file mode 100644 index 0000000000..dccf8f5819 --- /dev/null +++ b/client-src/utils/format-webpack-message.js @@ -0,0 +1,132 @@ +/** +MIT License +Copyright (c) 2015-present, Facebook, Inc. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import stripAnsi from "../modules/strip-ansi/index.js"; +// This file is based on https://github.com/facebook/create-react-app/blob/7b1a32be6ec9f99a6c9a3c66813f3ac09c4736b9/packages/react-dev-utils/formatWebpackMessages.js +// It's been edited to remove chalk and CRA-specific logic + +const friendlySyntaxErrorLabel = "Syntax error:"; + +// Cleans up webpack error messages. +function formatWebpackMessage(message, verbose) { + if (typeof message === "object" && message.message) { + const filteredModuleTrace = + message.moduleTrace && + message.moduleTrace.filter( + (trace) => + !/next-(middleware|client-pages|flight-(client|server))-loader\.js/.test( + trace.originName + ) + ); + message = + (message.moduleName ? `${stripAnsi(message.moduleName)}\n` : "") + + (message.file ? `${stripAnsi(message.file)}\n` : "") + + message.message + + (message.details && verbose ? `\n${message.details}` : "") + + (filteredModuleTrace && filteredModuleTrace.length && verbose + ? `\n\nImport trace for requested module:${filteredModuleTrace + .map((trace) => `\n${trace.originName}`) + .join("")}` + : "") + + (message.stack && verbose ? `\n${message.stack}` : ""); + } + 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((line) => !/Module [A-z ]+\(from/.test(line)); + + // Transform parsing error into syntax error + lines = lines.map((line) => { + const parsingError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec( + line + ); + if (!parsingError) { + return line; + } + const [, errorLine, errorColumn, errorMessage] = parsingError; + return `${friendlySyntaxErrorLabel} ${errorMessage} (${errorLine}:${errorColumn})`; + }); + + message = lines.join("\n"); + // Smoosh syntax errors (commonly found in CSS) + message = message.replace( + /SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g, + `${friendlySyntaxErrorLabel} $3 ($1:$2)\n` + ); + // Clean up export errors + message = message.replace( + /^.*export '(.+?)' was not found in '(.+?)'.*$/gm, + `Attempted import error: '$1' is not exported from '$2'.` + ); + message = message.replace( + /^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm, + `Attempted import error: '$2' does not contain a default export (imported as '$1').` + ); + message = message.replace( + /^.*export '(.+?)' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm, + `Attempted import error: '$1' is not exported from '$3' (imported as '$2').` + ); + lines = message.split("\n"); + + // Remove leading newline + if (lines.length > 2 && lines[1].trim() === "") { + lines.splice(1, 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:"), + ...lines.slice(2), + ]; + } + + if (!verbose) { + message = lines.join("\n"); + // Internal stacks are generally useless so we strip them... with the + // exception of stacks containing `webpack:` because they're normally + // from user code generated by Webpack. For more information see + // https://github.com/facebook/create-react-app/pull/1050 + message = message.replace( + /^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, + "" + // eslint-disable-next-line line-comment-position + ); // at ... ...:x:y + // eslint-disable-next-line line-comment-position + message = message.replace(/^\s*at\s(\n|$)/gm, ""); // at + lines = message.split("\n"); + } + + // Remove duplicated newlines + lines = lines.filter( + (line, index, arr) => + index === 0 || line.trim() !== "" || line.trim() !== arr[index - 1].trim() + ); + + // Reassemble the message + message = lines.join("\n"); + return message.trim(); +} + +export default formatWebpackMessage; diff --git a/test/e2e/__snapshots__/overlay.test.js.snap.webpack5 b/test/e2e/__snapshots__/overlay.test.js.snap.webpack5 index c8a56d4012..20efe665c7 100644 --- a/test/e2e/__snapshots__/overlay.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/overlay.test.js.snap.webpack5 @@ -70,8 +70,8 @@ exports[`overlay should not show initially, then show on an error and allow to c ERROR in ./foo.js 1:1

- Module parse failed: Unterminated template (1:1) You may need an - appropriate loader to handle this file type, currently no loaders are + ./foo.js Module parse failed: Unterminated template (1:1) You may need + an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders > \`;
@@ -157,8 +157,8 @@ exports[`overlay should not show initially, then show on an error, then hide on ERROR in ./foo.js 1:1

- Module parse failed: Unterminated template (1:1) You may need an - appropriate loader to handle this file type, currently no loaders are + ./foo.js Module parse failed: Unterminated template (1:1) You may need + an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders > \`;
@@ -244,8 +244,8 @@ exports[`overlay should not show initially, then show on an error, then show oth ERROR in ./foo.js 1:1

- Module parse failed: Unterminated template (1:1) You may need an - appropriate loader to handle this file type, currently no loaders are + ./foo.js Module parse failed: Unterminated template (1:1) You may need + an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders > \`;
@@ -294,8 +294,8 @@ exports[`overlay should not show initially, then show on an error, then show oth ERROR in ./foo.js 1:1

- Module parse failed: Unterminated template (1:1) You may need an - appropriate loader to handle this file type, currently no loaders are + ./foo.js Module parse failed: Unterminated template (1:1) You may need + an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders > \`;a
From c2495203a96005a1080d4fb7ba13e7198a923bc3 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 17 Apr 2022 07:41:07 +0530 Subject: [PATCH 2/4] fix: lint and debug --- client-src/utils/format-webpack-message.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client-src/utils/format-webpack-message.js b/client-src/utils/format-webpack-message.js index dccf8f5819..ef437eda13 100644 --- a/client-src/utils/format-webpack-message.js +++ b/client-src/utils/format-webpack-message.js @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import stripAnsi from "../modules/strip-ansi/index.js"; +import stripAnsi from "./stripAnsi.js"; // This file is based on https://github.com/facebook/create-react-app/blob/7b1a32be6ec9f99a6c9a3c66813f3ac09c4736b9/packages/react-dev-utils/formatWebpackMessages.js // It's been edited to remove chalk and CRA-specific logic diff --git a/package.json b/package.json index b819330d08..c65dfdeaa2 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "build:client": "rimraf ./client/* && babel client-src/ --out-dir client/ --ignore \"client-src/webpack.config.js\" --ignore \"client-src/modules\" && webpack --config client-src/webpack.config.js", "build:types": "rimraf ./types/* && tsc --declaration --emitDeclarationOnly --outDir types && node ./scripts/extend-webpack-types.js && prettier \"types/**/*.ts\" --write && prettier \"types/**/*.ts\" --write", "build": "npm-run-all -p \"build:**\"", - "test:only": "jest", + "test:only": "jest overlay.test.js", "test:coverage": "npm run test:only -- --coverage", "test:watch": "npm run test:coverage --watch", "test": "npm run test:coverage", From 0269db43806c43fc60c891099253ded22f0c96db Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 17 Apr 2022 07:47:34 +0530 Subject: [PATCH 3/4] test: fix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c65dfdeaa2..b819330d08 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "build:client": "rimraf ./client/* && babel client-src/ --out-dir client/ --ignore \"client-src/webpack.config.js\" --ignore \"client-src/modules\" && webpack --config client-src/webpack.config.js", "build:types": "rimraf ./types/* && tsc --declaration --emitDeclarationOnly --outDir types && node ./scripts/extend-webpack-types.js && prettier \"types/**/*.ts\" --write && prettier \"types/**/*.ts\" --write", "build": "npm-run-all -p \"build:**\"", - "test:only": "jest overlay.test.js", + "test:only": "jest", "test:coverage": "npm run test:only -- --coverage", "test:watch": "npm run test:coverage --watch", "test": "npm run test:coverage", From 3d8c2d4467324f4b029f4087ad772d7e4ed3d18c Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 17 Apr 2022 08:16:55 +0530 Subject: [PATCH 4/4] test: update snapshot --- .../multi-compiler.test.js.snap.webpack5 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/e2e/__snapshots__/multi-compiler.test.js.snap.webpack5 b/test/e2e/__snapshots__/multi-compiler.test.js.snap.webpack5 index ca63857c9e..3537ab5f38 100644 --- a/test/e2e/__snapshots__/multi-compiler.test.js.snap.webpack5 +++ b/test/e2e/__snapshots__/multi-compiler.test.js.snap.webpack5 @@ -55,13 +55,13 @@ Array [ "[HMR] Cannot apply update. Need to do a full reload!", "[HMR] Error: Aborted because ./browser.js is not accepted Update propagation: ./browser.js - at applyHandler (http://127.0.0.1:8103/browser.js:1034:31) - at http://127.0.0.1:8103/browser.js:733:21 + at applyHandler (http://127.0.0.1:8103/browser.js:1045:31) + at http://127.0.0.1:8103/browser.js:744:21 at Array.map () - at internalApply (http://127.0.0.1:8103/browser.js:732:54) - at http://127.0.0.1:8103/browser.js:702:26 - at waitForBlockingPromises (http://127.0.0.1:8103/browser.js:656:48) - at http://127.0.0.1:8103/browser.js:700:24", + at internalApply (http://127.0.0.1:8103/browser.js:743:54) + at http://127.0.0.1:8103/browser.js:713:26 + at waitForBlockingPromises (http://127.0.0.1:8103/browser.js:667:48) + at http://127.0.0.1:8103/browser.js:711:24", "[HMR] Waiting for update signal from WDS...", "Hello from the browser", "[webpack-dev-server] Hot Module Replacement enabled.",