Skip to content

Commit

Permalink
feat: show better parse error in build (#14600)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored Oct 12, 2023
1 parent b43b4df commit 84df7db
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 23 deletions.
57 changes: 36 additions & 21 deletions packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -814,6 +797,38 @@ function mergeAcceptedUrls<T>(orderedUrls: Array<Set<T> | 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,
Expand Down
8 changes: 6 additions & 2 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 84df7db

Please sign in to comment.