From 84df7db1ea34b60a727628f8228f3ac31a27715d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 12 Oct 2023 23:20:33 +0900 Subject: [PATCH] feat: show better parse error in build (#14600) --- .../vite/src/node/plugins/importAnalysis.ts | 57 ++++++++++++------- .../src/node/plugins/importAnalysisBuild.ts | 8 ++- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 5b701dc692691c..0681a38caf63d7 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -225,28 +225,11 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { try { ;[imports, exports] = parseImports(source) } catch (e: any) { - const isVue = importer.endsWith('.vue') - const isJsx = importer.endsWith('.jsx') || importer.endsWith('.tsx') - const maybeJSX = !isVue && isJSRequest(importer) - - const msg = isVue - ? `Install @vitejs/plugin-vue to handle .vue files.` - : maybeJSX - ? isJsx - ? `If you use tsconfig.json, make sure to not set jsx to preserve.` - : `If you are using JSX, make sure to name the file with the .jsx or .tsx extension.` - : `You may need to install appropriate plugins to handle the ${path.extname( - importer, - )} file format, or if it's an asset, add "**/*${path.extname( - importer, - )}" to \`assetsInclude\` in your configuration.` - - this.error( - `Failed to parse source for import analysis because the content ` + - `contains invalid JS syntax. ` + - msg, - e.idx, + const { message, showCodeFrame } = createParseErrorInfo( + importer, + source, ) + this.error(message, showCodeFrame ? e.idx : undefined) } const depsOptimizer = getDepsOptimizer(config, ssr) @@ -814,6 +797,38 @@ function mergeAcceptedUrls(orderedUrls: Array | undefined>) { return acceptedUrls } +export function createParseErrorInfo( + importer: string, + source: string, +): { message: string; showCodeFrame: boolean } { + const isVue = importer.endsWith('.vue') + const isJsx = importer.endsWith('.jsx') || importer.endsWith('.tsx') + const maybeJSX = !isVue && isJSRequest(importer) + const probablyBinary = source.includes( + '\ufffd' /* unicode replacement character */, + ) + + const msg = isVue + ? `Install @vitejs/plugin-vue to handle .vue files.` + : maybeJSX + ? isJsx + ? `If you use tsconfig.json, make sure to not set jsx to preserve.` + : `If you are using JSX, make sure to name the file with the .jsx or .tsx extension.` + : `You may need to install appropriate plugins to handle the ${path.extname( + importer, + )} file format, or if it's an asset, add "**/*${path.extname( + importer, + )}" to \`assetsInclude\` in your configuration.` + + return { + message: + `Failed to parse source for import analysis because the content ` + + `contains invalid JS syntax. ` + + msg, + showCodeFrame: !probablyBinary, + } +} + export function interopNamedImports( str: MagicString, importSpecifier: ImportSpecifier, diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index e4d6ab6e4375ed..822b99d43ead18 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -24,7 +24,7 @@ import { toOutputFilePathInJS } from '../build' import { genSourceMapUrl } from '../server/sourcemap' import { getDepsOptimizer, optimizedDepNeedsInterop } from '../optimizer' import { removedPureCssFilesCache } from './css' -import { interopNamedImports } from './importAnalysis' +import { createParseErrorInfo, interopNamedImports } from './importAnalysis' type FileDep = { url: string @@ -223,7 +223,11 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { try { imports = parseImports(source)[0] } catch (e: any) { - this.error(e, e.idx) + const { message, showCodeFrame } = createParseErrorInfo( + importer, + source, + ) + this.error(message, showCodeFrame ? e.idx : undefined) } if (!imports.length) {