diff --git a/.changeset/pretty-hairs-press.md b/.changeset/pretty-hairs-press.md new file mode 100644 index 000000000..6a1b469f7 --- /dev/null +++ b/.changeset/pretty-hairs-press.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/vite-plugin-svelte': patch +--- + +include stack and filename in error reporting for svelte preprocess errors diff --git a/packages/vite-plugin-svelte/src/index.ts b/packages/vite-plugin-svelte/src/index.ts index c3883b0d3..e7674641b 100644 --- a/packages/vite-plugin-svelte/src/index.ts +++ b/packages/vite-plugin-svelte/src/index.ts @@ -170,7 +170,7 @@ export function svelte(inlineOptions?: Partial): Plugin { try { compileData = await compileSvelte(svelteRequest, code, options); } catch (e) { - throw toRollupError(e); + throw toRollupError(e, options); } logCompilerWarnings(compileData.compiled.warnings, options); cache.update(compileData); diff --git a/packages/vite-plugin-svelte/src/utils/compile.ts b/packages/vite-plugin-svelte/src/utils/compile.ts index 166d31b2e..75ca72e92 100644 --- a/packages/vite-plugin-svelte/src/utils/compile.ts +++ b/packages/vite-plugin-svelte/src/utils/compile.ts @@ -37,7 +37,13 @@ const _createCompileSvelte = (makeHot: Function) => let preprocessed; if (options.preprocess) { - preprocessed = await preprocess(code, options.preprocess, { filename }); + try { + preprocessed = await preprocess(code, options.preprocess, { filename }); + } catch (e) { + e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`; + throw e; + } + if (preprocessed.dependencies) dependencies.push(...preprocessed.dependencies); if (preprocessed.map) compileOptions.sourcemap = preprocessed.map; } diff --git a/packages/vite-plugin-svelte/src/utils/error.ts b/packages/vite-plugin-svelte/src/utils/error.ts index 4029bcbb2..0f5b8d9c2 100644 --- a/packages/vite-plugin-svelte/src/utils/error.ts +++ b/packages/vite-plugin-svelte/src/utils/error.ts @@ -1,5 +1,5 @@ import { RollupError } from 'rollup'; -import { Warning } from './options'; +import { ResolvedOptions, Warning } from './options'; import { buildExtendedLogMessage } from './log'; import { PartialMessage } from 'esbuild'; @@ -8,15 +8,15 @@ import { PartialMessage } from 'esbuild'; * @param error a svelte compiler error, which is a mix of Warning and an error * @returns {RollupError} the converted error */ -export function toRollupError(error: Warning & Error): RollupError { - const { filename, frame, start, code, name } = error; +export function toRollupError(error: Warning & Error, options: ResolvedOptions): RollupError { + const { filename, frame, start, code, name, stack } = error; const rollupError: RollupError = { name, // needed otherwise sveltekit coalesce_to_error turns it into a string id: filename, message: buildExtendedLogMessage(error), // include filename:line:column so that it's clickable frame: formatFrameForVite(frame), code, - stack: '' + stack: options.isBuild || options.isDebug || !frame ? stack : '' }; if (start) { rollupError.loc = { @@ -33,8 +33,8 @@ export function toRollupError(error: Warning & Error): RollupError { * @param error a svelte compiler error, which is a mix of Warning and an error * @returns {PartialMessage} the converted error */ -export function toESBuildError(error: Warning & Error): PartialMessage { - const { filename, frame, start } = error; +export function toESBuildError(error: Warning & Error, options: ResolvedOptions): PartialMessage { + const { filename, frame, start, stack } = error; const partialMessage: PartialMessage = { text: buildExtendedLogMessage(error) }; @@ -46,6 +46,9 @@ export function toESBuildError(error: Warning & Error): PartialMessage { lineText: lineFromFrame(start.line, frame) // needed to get a meaningful error message on cli }; } + if (options.isBuild || options.isDebug || !frame) { + partialMessage.detail = stack; + } return partialMessage; } diff --git a/packages/vite-plugin-svelte/src/utils/esbuild.ts b/packages/vite-plugin-svelte/src/utils/esbuild.ts index 32f8855de..d44083885 100644 --- a/packages/vite-plugin-svelte/src/utils/esbuild.ts +++ b/packages/vite-plugin-svelte/src/utils/esbuild.ts @@ -27,7 +27,7 @@ export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin { const contents = await compileSvelte(options, { filename, code }); return { contents }; } catch (e) { - return { errors: [toESBuildError(e)] }; + return { errors: [toESBuildError(e, options)] }; } }); } @@ -73,7 +73,12 @@ async function compileSvelte( let preprocessed; if (options.preprocess) { - preprocessed = await preprocess(code, options.preprocess, { filename }); + try { + preprocessed = await preprocess(code, options.preprocess, { filename }); + } catch (e) { + e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`; + throw e; + } if (preprocessed.map) compileOptions.sourcemap = preprocessed.map; } diff --git a/packages/vite-plugin-svelte/src/utils/log.ts b/packages/vite-plugin-svelte/src/utils/log.ts index b8b0e0273..4dbc52720 100644 --- a/packages/vite-plugin-svelte/src/utils/log.ts +++ b/packages/vite-plugin-svelte/src/utils/log.ts @@ -164,7 +164,10 @@ export function buildExtendedLogMessage(w: Warning) { parts.push(':', w.start.line, ':', w.start.column); } if (w.message) { - parts.push(' ', w.message); + if (parts.length > 0) { + parts.push(' '); + } + parts.push(w.message); } return parts.join(''); } diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index d2806ebaa..0fd35fa3b 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -82,7 +82,8 @@ export async function preResolveOptions( // extras root: viteConfigWithResolvedRoot.root!, isBuild: viteEnv.command === 'build', - isServe: viteEnv.command === 'serve' + isServe: viteEnv.command === 'serve', + isDebug: process.env.DEBUG != null }; // configFile of svelteConfig contains the absolute path it was loaded from, // prefer it over the possibly relative inline path @@ -491,6 +492,7 @@ export interface PreResolvedOptions extends Options { root: string; isBuild: boolean; isServe: boolean; + isDebug: boolean; } export interface ResolvedOptions extends PreResolvedOptions {