@sveltejs/vite-plugin-svelte 1.0.0-next.29 → 1.0.0-next.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ import { ensureWatchedFile, setupWatchers } from './utils/watch';
17
17
  import { resolveViaPackageJsonSvelte } from './utils/resolve';
18
18
  import { addExtraPreprocessors } from './utils/preprocess';
19
19
  import { PartialResolvedId } from 'rollup';
20
+ import { toRollupError } from './utils/error';
20
21
 
21
22
  export function svelte(inlineOptions?: Partial<Options>): Plugin {
22
23
  if (process.env.DEBUG != null) {
@@ -94,11 +95,9 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
94
95
  }
95
96
  },
96
97
 
97
- async resolveId(importee, importer, opts, _ssr) {
98
- // @ts-expect-error anticipate vite deprecating forth parameter and rely on `opts.ssr` instead`
99
- // see https://github.com/vitejs/vite/discussions/5109
100
- const ssr: boolean = _ssr === true || opts.ssr;
101
- const svelteRequest = requestParser(importee, !!ssr);
98
+ async resolveId(importee, importer, opts) {
99
+ const ssr = !!opts?.ssr;
100
+ const svelteRequest = requestParser(importee, ssr);
102
101
  if (svelteRequest?.query.svelte) {
103
102
  if (svelteRequest.query.type === 'style') {
104
103
  // return cssId with root prefix so postcss pipeline of vite finds the directory correctly
@@ -149,10 +148,8 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
149
148
  },
150
149
 
151
150
  async transform(code, id, opts) {
152
- // @ts-expect-error anticipate vite changing third parameter as options object
153
- // see https://github.com/vitejs/vite/discussions/5109
154
- const ssr: boolean = opts === true || opts?.ssr;
155
- const svelteRequest = requestParser(id, !!ssr);
151
+ const ssr = !!opts?.ssr;
152
+ const svelteRequest = requestParser(id, ssr);
156
153
  if (!svelteRequest) {
157
154
  return;
158
155
  }
@@ -169,7 +166,12 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
169
166
  log.error('failed to transform tagged svelte request', svelteRequest);
170
167
  throw new Error(`failed to transform tagged svelte request for id ${id}`);
171
168
  }
172
- const compileData = await compileSvelte(svelteRequest, code, options);
169
+ let compileData;
170
+ try {
171
+ compileData = await compileSvelte(svelteRequest, code, options);
172
+ } catch (e) {
173
+ throw toRollupError(e);
174
+ }
173
175
  logCompilerWarnings(compileData.compiled.warnings, options);
174
176
  cache.update(compileData);
175
177
  if (compileData.dependencies?.length && options.server) {
@@ -0,0 +1,92 @@
1
+ import { RollupError } from 'rollup';
2
+ import { Warning } from './options';
3
+ import { buildExtendedLogMessage } from './log';
4
+ import { PartialMessage } from 'esbuild';
5
+
6
+ /**
7
+ * convert an error thrown by svelte.compile to a RollupError so that vite displays it in a user friendly way
8
+ * @param error a svelte compiler error, which is a mix of Warning and an error
9
+ * @returns {RollupError} the converted error
10
+ */
11
+ export function toRollupError(error: Warning & Error): RollupError {
12
+ const { filename, frame, start, code, name } = error;
13
+ const rollupError: RollupError = {
14
+ name, // needed otherwise sveltekit coalesce_to_error turns it into a string
15
+ id: filename,
16
+ message: buildExtendedLogMessage(error), // include filename:line:column so that it's clickable
17
+ frame: formatFrameForVite(frame),
18
+ code,
19
+ stack: ''
20
+ };
21
+ if (start) {
22
+ rollupError.loc = {
23
+ line: start.line,
24
+ column: start.column,
25
+ file: filename
26
+ };
27
+ }
28
+ return rollupError;
29
+ }
30
+
31
+ /**
32
+ * convert an error thrown by svelte.compile to an esbuild PartialMessage
33
+ * @param error a svelte compiler error, which is a mix of Warning and an error
34
+ * @returns {PartialMessage} the converted error
35
+ */
36
+ export function toESBuildError(error: Warning & Error): PartialMessage {
37
+ const { filename, frame, start } = error;
38
+ const partialMessage: PartialMessage = {
39
+ text: buildExtendedLogMessage(error)
40
+ };
41
+ if (start) {
42
+ partialMessage.location = {
43
+ line: start.line,
44
+ column: start.column,
45
+ file: filename,
46
+ lineText: lineFromFrame(start.line, frame) // needed to get a meaningful error message on cli
47
+ };
48
+ }
49
+ return partialMessage;
50
+ }
51
+
52
+ /**
53
+ * extract line with number from codeframe
54
+ */
55
+ function lineFromFrame(lineNo: number, frame?: string): string {
56
+ if (!frame) {
57
+ return '';
58
+ }
59
+ const lines = frame.split('\n');
60
+ const errorLine = lines.find((line) => line.trimStart().startsWith(`${lineNo}: `));
61
+ return errorLine ? errorLine.substring(errorLine.indexOf(': ') + 3) : '';
62
+ }
63
+
64
+ /**
65
+ * vite error overlay expects a specific format to show frames
66
+ * this reformats svelte frame (colon separated, less whitespace)
67
+ * to one that vite displays on overlay ( pipe separated, more whitespace)
68
+ * e.g.
69
+ * ```
70
+ * 1: foo
71
+ * 2: bar;
72
+ * ^
73
+ * 3: baz
74
+ * ```
75
+ * to
76
+ * ```
77
+ * 1 | foo
78
+ * 2 | bar;
79
+ * ^
80
+ * 3 | baz
81
+ * ```
82
+ * @see https://github.com/vitejs/vite/blob/96591bf9989529de839ba89958755eafe4c445ae/packages/vite/src/client/overlay.ts#L116
83
+ */
84
+ function formatFrameForVite(frame?: string): string {
85
+ if (!frame) {
86
+ return '';
87
+ }
88
+ return frame
89
+ .split('\n')
90
+ .map((line) => (line.match(/^\s+\^/) ? ' ' + line : ' ' + line.replace(':', ' | ')))
91
+ .join('\n');
92
+ }
@@ -4,6 +4,7 @@ import { DepOptimizationOptions } from 'vite';
4
4
  import { Compiled } from './compile';
5
5
  import { log } from './log';
6
6
  import { CompileOptions, ResolvedOptions } from './options';
7
+ import { toESBuildError } from './error';
7
8
 
8
9
  type EsbuildOptions = NonNullable<DepOptimizationOptions['esbuildOptions']>;
9
10
  type EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];
@@ -20,8 +21,12 @@ export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
20
21
 
21
22
  build.onLoad({ filter: svelteFilter }, async ({ path: filename }) => {
22
23
  const code = await fs.readFile(filename, 'utf8');
23
- const contents = await compileSvelte(options, { filename, code });
24
- return { contents };
24
+ try {
25
+ const contents = await compileSvelte(options, { filename, code });
26
+ return { contents };
27
+ } catch (e) {
28
+ return { errors: [toESBuildError(e)] };
29
+ }
25
30
  });
26
31
  }
27
32
  };
package/src/utils/log.ts CHANGED
@@ -155,7 +155,7 @@ function warnBuild(w: Warning) {
155
155
  log.warn.enabled && log.warn(buildExtendedLogMessage(w), w.frame);
156
156
  }
157
157
 
158
- function buildExtendedLogMessage(w: Warning) {
158
+ export function buildExtendedLogMessage(w: Warning) {
159
159
  const parts = [];
160
160
  if (w.filename) {
161
161
  parts.push(w.filename);
@@ -121,6 +121,7 @@ function mergeOptions(
121
121
  viteConfig: UserConfig,
122
122
  viteEnv: ConfigEnv
123
123
  ): ResolvedOptions {
124
+ // @ts-ignore
124
125
  const merged = {
125
126
  ...defaultOptions,
126
127
  ...svelteConfig,
@@ -137,7 +138,9 @@ function mergeOptions(
137
138
  root: viteConfig.root!,
138
139
  isProduction: viteEnv.mode === 'production',
139
140
  isBuild: viteEnv.command === 'build',
140
- isServe: viteEnv.command === 'serve'
141
+ isServe: viteEnv.command === 'serve',
142
+ // @ts-expect-error we don't declare kit property of svelte config but read it once here to identify kit projects
143
+ isSvelteKit: !!svelteConfig?.kit
141
144
  };
142
145
  // configFile of svelteConfig contains the absolute path it was loaded from,
143
146
  // prefer it over the possibly relative inline path
@@ -485,6 +488,7 @@ export interface ResolvedOptions extends Options {
485
488
  isBuild: boolean;
486
489
  isServe: boolean;
487
490
  server?: ViteDevServer;
491
+ isSvelteKit?: boolean;
488
492
  }
489
493
 
490
494
  export type {
@@ -14,7 +14,13 @@ export function resolveViaPackageJsonSvelte(importee: string, importer?: string)
14
14
  }
15
15
 
16
16
  function isBareImport(importee: string): boolean {
17
- if (!importee || importee[0] === '.' || importee[0] === '\0' || path.isAbsolute(importee)) {
17
+ if (
18
+ !importee ||
19
+ importee[0] === '.' ||
20
+ importee[0] === '\0' ||
21
+ importee.includes(':') ||
22
+ path.isAbsolute(importee)
23
+ ) {
18
24
  return false;
19
25
  }
20
26
  const parts = importee.split('/');
@@ -17,7 +17,7 @@ export function setupWatchers(
17
17
  return;
18
18
  }
19
19
  const { watcher, ws } = server;
20
- const { configFile: viteConfigFile, root, server: serverConfig } = server.config;
20
+ const { root, server: serverConfig } = server.config;
21
21
 
22
22
  const emitChangeEventOnDependants = (filename: string) => {
23
23
  const dependants = cache.getDependants(filename);
@@ -42,12 +42,9 @@ export function setupWatchers(
42
42
  };
43
43
 
44
44
  const triggerViteRestart = (filename: string) => {
45
- // vite restart is triggered by simulating a change to vite config. This requires that vite config exists
46
- // also we do not restart in middleware-mode as it could be risky
47
- if (!!viteConfigFile && !serverConfig.middlewareMode) {
48
- log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
49
- watcher.emit('change', viteConfigFile);
50
- } else {
45
+ if (serverConfig.middlewareMode || options.isSvelteKit) {
46
+ // in middlewareMode or for sveltekit we can't restart the server automatically
47
+ // show the user an overlay instead
51
48
  const message =
52
49
  'Svelte config change detected, restart your dev process to apply the changes.';
53
50
  log.info(message, filename);
@@ -55,6 +52,9 @@ export function setupWatchers(
55
52
  type: 'error',
56
53
  err: { message, stack: '', plugin: 'vite-plugin-svelte', id: filename }
57
54
  });
55
+ } else {
56
+ log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
57
+ server.restart(!!options.experimental?.prebundleSvelteLibraries);
58
58
  }
59
59
  };
60
60