@sveltejs/vite-plugin-svelte 1.0.0-next.30 → 1.0.0-next.34

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
@@ -9,14 +9,17 @@ import {
9
9
  validateInlineOptions,
10
10
  Options,
11
11
  ResolvedOptions,
12
- resolveOptions
12
+ resolveOptions,
13
+ patchResolvedViteConfig,
14
+ preResolveOptions
13
15
  } from './utils/options';
14
16
  import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache';
15
17
 
16
18
  import { ensureWatchedFile, setupWatchers } from './utils/watch';
17
19
  import { resolveViaPackageJsonSvelte } from './utils/resolve';
18
- import { addExtraPreprocessors } from './utils/preprocess';
19
20
  import { PartialResolvedId } from 'rollup';
21
+ import { toRollupError } from './utils/error';
22
+ import { handleOptimizeDeps } from './utils/optimizer';
20
23
 
21
24
  export function svelte(inlineOptions?: Partial<Options>): Plugin {
22
25
  if (process.env.DEBUG != null) {
@@ -50,21 +53,27 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
50
53
  } else if (config.logLevel) {
51
54
  log.setLevel(config.logLevel);
52
55
  }
53
- options = await resolveOptions(inlineOptions, config, configEnv);
56
+ // @ts-expect-error temporarily lend the options variable until fixed in configResolved
57
+ options = await preResolveOptions(inlineOptions, config, configEnv);
54
58
  // extra vite config
55
59
  const extraViteConfig = buildExtraViteConfig(options, config, configEnv);
56
60
  log.debug('additional vite config', extraViteConfig);
57
- return extraViteConfig as Partial<UserConfig>;
61
+ return extraViteConfig;
58
62
  },
59
63
 
60
64
  async configResolved(config) {
61
- addExtraPreprocessors(options, config);
65
+ options = resolveOptions(options, config);
66
+ patchResolvedViteConfig(config, options);
62
67
  requestParser = buildIdParser(options);
63
68
  compileSvelte = createCompileSvelte(options);
64
69
  viteConfig = config;
65
70
  log.debug('resolved options', options);
66
71
  },
67
72
 
73
+ async buildStart() {
74
+ await handleOptimizeDeps(options, viteConfig);
75
+ },
76
+
68
77
  configureServer(server) {
69
78
  // eslint-disable-next-line no-unused-vars
70
79
  options.server = server;
@@ -94,11 +103,9 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
94
103
  }
95
104
  },
96
105
 
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);
106
+ async resolveId(importee, importer, opts) {
107
+ const ssr = !!opts?.ssr;
108
+ const svelteRequest = requestParser(importee, ssr);
102
109
  if (svelteRequest?.query.svelte) {
103
110
  if (svelteRequest.query.type === 'style') {
104
111
  // return cssId with root prefix so postcss pipeline of vite finds the directory correctly
@@ -149,10 +156,8 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
149
156
  },
150
157
 
151
158
  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);
159
+ const ssr = !!opts?.ssr;
160
+ const svelteRequest = requestParser(id, ssr);
156
161
  if (!svelteRequest) {
157
162
  return;
158
163
  }
@@ -169,7 +174,12 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
169
174
  log.error('failed to transform tagged svelte request', svelteRequest);
170
175
  throw new Error(`failed to transform tagged svelte request for id ${id}`);
171
176
  }
172
- const compileData = await compileSvelte(svelteRequest, code, options);
177
+ let compileData;
178
+ try {
179
+ compileData = await compileSvelte(svelteRequest, code, options);
180
+ } catch (e) {
181
+ throw toRollupError(e);
182
+ }
173
183
  logCompilerWarnings(compileData.compiled.warnings, options);
174
184
  cache.update(compileData);
175
185
  if (compileData.dependencies?.length && options.server) {
@@ -184,7 +184,12 @@ export function needsOptimization(dep: string, localRequire: NodeRequire): boole
184
184
  const pkg = depData.pkg;
185
185
  // only optimize if is cjs, using the below as heuristic
186
186
  // see https://github.com/sveltejs/vite-plugin-svelte/issues/162
187
- return pkg.main && !pkg.module && !pkg.exports;
187
+ const isCjs = pkg.main && !pkg.module && !pkg.exports;
188
+ if (!isCjs) return false;
189
+ // ensure entry is js so vite can prebundle it
190
+ // see https://github.com/sveltejs/vite-plugin-svelte/issues/233
191
+ const entryExt = path.extname(pkg.main);
192
+ return !entryExt || entryExt === '.js' || entryExt === '.cjs';
188
193
  }
189
194
 
190
195
  interface DependencyData {
@@ -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,11 +4,14 @@ 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];
10
11
  type EsbuildPluginBuild = Parameters<EsbuildPlugin['setup']>[0];
11
12
 
13
+ export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade';
14
+
12
15
  export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
13
16
  return {
14
17
  name: 'vite-plugin-svelte:optimize-svelte',
@@ -20,8 +23,12 @@ export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
20
23
 
21
24
  build.onLoad({ filter: svelteFilter }, async ({ path: filename }) => {
22
25
  const code = await fs.readFile(filename, 'utf8');
23
- const contents = await compileSvelte(options, { filename, code });
24
- return { contents };
26
+ try {
27
+ const contents = await compileSvelte(options, { filename, code });
28
+ return { contents };
29
+ } catch (e) {
30
+ return { errors: [toESBuildError(e)] };
31
+ }
25
32
  });
26
33
  }
27
34
  };
@@ -59,6 +66,7 @@ async function compileSvelte(
59
66
  ...options.compilerOptions,
60
67
  css: true,
61
68
  filename,
69
+ format: 'esm',
62
70
  generate: 'dom'
63
71
  };
64
72
 
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);
@@ -0,0 +1,43 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { optimizeDeps, ResolvedConfig } from 'vite';
4
+ import { ResolvedOptions } from './options';
5
+
6
+ // List of options that changes the prebundling result
7
+ const PREBUNDLE_SENSITIVE_OPTIONS: (keyof ResolvedOptions)[] = [
8
+ 'compilerOptions',
9
+ 'configFile',
10
+ 'experimental',
11
+ 'extensions',
12
+ 'ignorePluginPreprocessors',
13
+ 'preprocess'
14
+ ];
15
+
16
+ export async function handleOptimizeDeps(options: ResolvedOptions, viteConfig: ResolvedConfig) {
17
+ if (!options.experimental.prebundleSvelteLibraries || !viteConfig.cacheDir) return;
18
+
19
+ const viteMetadataPath = path.resolve(viteConfig.cacheDir, '_metadata.json');
20
+
21
+ if (!fs.existsSync(viteMetadataPath)) return;
22
+
23
+ const svelteMetadataPath = path.resolve(viteConfig.cacheDir, '_svelte_metadata.json');
24
+ const currentSvelteMetadata = JSON.stringify(generateSvelteMetadata(options), (_, value) => {
25
+ return typeof value === 'function' ? value.toString() : value;
26
+ });
27
+
28
+ if (fs.existsSync(svelteMetadataPath)) {
29
+ const existingSvelteMetadata = fs.readFileSync(svelteMetadataPath, 'utf8');
30
+ if (existingSvelteMetadata === currentSvelteMetadata) return;
31
+ }
32
+
33
+ await optimizeDeps(viteConfig, true);
34
+ fs.writeFileSync(svelteMetadataPath, currentSvelteMetadata);
35
+ }
36
+
37
+ function generateSvelteMetadata(options: ResolvedOptions) {
38
+ const metadata: Record<string, any> = {};
39
+ for (const key of PREBUNDLE_SENSITIVE_OPTIONS) {
40
+ metadata[key] = options[key];
41
+ }
42
+ return metadata;
43
+ }
@@ -1,5 +1,12 @@
1
1
  /* eslint-disable no-unused-vars */
2
- import { ConfigEnv, DepOptimizationOptions, UserConfig, ViteDevServer, normalizePath } from 'vite';
2
+ import {
3
+ ConfigEnv,
4
+ DepOptimizationOptions,
5
+ ResolvedConfig,
6
+ UserConfig,
7
+ ViteDevServer,
8
+ normalizePath
9
+ } from 'vite';
3
10
  import { log } from './log';
4
11
  import { loadSvelteConfig } from './load-svelte-config';
5
12
  import { SVELTE_HMR_IMPORTS, SVELTE_IMPORTS, SVELTE_RESOLVE_MAIN_FIELDS } from './constants';
@@ -15,7 +22,8 @@ import {
15
22
  import path from 'path';
16
23
  import { findRootSvelteDependencies, needsOptimization, SvelteDependency } from './dependencies';
17
24
  import { createRequire } from 'module';
18
- import { esbuildSveltePlugin } from './esbuild';
25
+ import { esbuildSveltePlugin, facadeEsbuildSveltePluginName } from './esbuild';
26
+ import { addExtraPreprocessors } from './preprocess';
19
27
 
20
28
  const knownOptions = new Set([
21
29
  'configFile',
@@ -32,33 +40,85 @@ const knownOptions = new Set([
32
40
  'experimental'
33
41
  ]);
34
42
 
35
- function buildDefaultOptions(isProduction: boolean, emitCss = true): Partial<Options> {
36
- // no hmr in prod, only inject css in dev if emitCss is false
37
- const hot = isProduction
38
- ? false
39
- : {
40
- // emit for prod, emit in dev unless css hmr is disabled
41
- injectCss: !emitCss
42
- };
43
+ export function validateInlineOptions(inlineOptions?: Partial<Options>) {
44
+ const invalidKeys = Object.keys(inlineOptions || {}).filter((key) => !knownOptions.has(key));
45
+ if (invalidKeys.length) {
46
+ log.warn(`invalid plugin options "${invalidKeys.join(', ')}" in config`, inlineOptions);
47
+ }
48
+ }
49
+
50
+ // used in config phase, merges the default options, svelte config, and inline options
51
+ export async function preResolveOptions(
52
+ inlineOptions: Partial<Options> = {},
53
+ viteUserConfig: UserConfig,
54
+ viteEnv: ConfigEnv
55
+ ): Promise<PreResolvedOptions> {
56
+ const viteConfigWithResolvedRoot: UserConfig = {
57
+ ...viteUserConfig,
58
+ root: resolveViteRoot(viteUserConfig)
59
+ };
43
60
  const defaultOptions: Partial<Options> = {
44
61
  extensions: ['.svelte'],
45
- hot,
46
- emitCss,
62
+ emitCss: true,
47
63
  compilerOptions: {
48
- format: 'esm',
49
- css: !emitCss,
50
- dev: !isProduction
64
+ format: 'esm'
51
65
  }
52
66
  };
53
- log.debug(`default options for ${isProduction ? 'production' : 'development'}`, defaultOptions);
54
- return defaultOptions;
67
+ const svelteConfig = await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions);
68
+ const merged = {
69
+ ...defaultOptions,
70
+ ...svelteConfig,
71
+ ...inlineOptions,
72
+ compilerOptions: {
73
+ ...defaultOptions?.compilerOptions,
74
+ ...svelteConfig?.compilerOptions,
75
+ ...inlineOptions?.compilerOptions
76
+ },
77
+ experimental: {
78
+ ...defaultOptions?.experimental,
79
+ ...svelteConfig?.experimental,
80
+ ...inlineOptions?.experimental
81
+ },
82
+ // extras
83
+ root: viteConfigWithResolvedRoot.root!,
84
+ isBuild: viteEnv.command === 'build',
85
+ isServe: viteEnv.command === 'serve'
86
+ };
87
+ // configFile of svelteConfig contains the absolute path it was loaded from,
88
+ // prefer it over the possibly relative inline path
89
+ if (svelteConfig?.configFile) {
90
+ merged.configFile = svelteConfig.configFile;
91
+ }
92
+ return merged;
55
93
  }
56
94
 
57
- export function validateInlineOptions(inlineOptions?: Partial<Options>) {
58
- const invalidKeys = Object.keys(inlineOptions || {}).filter((key) => !knownOptions.has(key));
59
- if (invalidKeys.length) {
60
- log.warn(`invalid plugin options "${invalidKeys.join(', ')}" in config`, inlineOptions);
61
- }
95
+ // used in configResolved phase, merges a contextual default config, pre-resolved options, and some preprocessors.
96
+ // also validates the final config.
97
+ export function resolveOptions(
98
+ preResolveOptions: PreResolvedOptions,
99
+ viteConfig: ResolvedConfig
100
+ ): ResolvedOptions {
101
+ const defaultOptions: Partial<Options> = {
102
+ hot: viteConfig.isProduction ? false : { injectCss: !preResolveOptions.emitCss },
103
+ compilerOptions: {
104
+ css: !preResolveOptions.emitCss,
105
+ dev: !viteConfig.isProduction
106
+ }
107
+ };
108
+ const merged: ResolvedOptions = {
109
+ ...defaultOptions,
110
+ ...preResolveOptions,
111
+ compilerOptions: {
112
+ ...defaultOptions.compilerOptions,
113
+ ...preResolveOptions.compilerOptions
114
+ },
115
+ root: viteConfig.root,
116
+ isProduction: viteConfig.isProduction
117
+ };
118
+ addExtraPreprocessors(merged, viteConfig);
119
+ enforceOptionsForHmr(merged);
120
+ enforceOptionsForProduction(merged);
121
+ return merged;
62
122
  }
63
123
 
64
124
  function enforceOptionsForHmr(options: ResolvedOptions) {
@@ -114,66 +174,6 @@ function enforceOptionsForProduction(options: ResolvedOptions) {
114
174
  }
115
175
  }
116
176
 
117
- function mergeOptions(
118
- defaultOptions: Partial<Options>,
119
- svelteConfig: Partial<Options>,
120
- inlineOptions: Partial<Options>,
121
- viteConfig: UserConfig,
122
- viteEnv: ConfigEnv
123
- ): ResolvedOptions {
124
- const merged = {
125
- ...defaultOptions,
126
- ...svelteConfig,
127
- ...inlineOptions,
128
- compilerOptions: {
129
- ...defaultOptions.compilerOptions,
130
- ...(svelteConfig?.compilerOptions || {}),
131
- ...(inlineOptions?.compilerOptions || {})
132
- },
133
- experimental: {
134
- ...(svelteConfig?.experimental || {}),
135
- ...(inlineOptions?.experimental || {})
136
- },
137
- root: viteConfig.root!,
138
- isProduction: viteEnv.mode === 'production',
139
- isBuild: viteEnv.command === 'build',
140
- isServe: viteEnv.command === 'serve'
141
- };
142
- // configFile of svelteConfig contains the absolute path it was loaded from,
143
- // prefer it over the possibly relative inline path
144
- if (svelteConfig?.configFile) {
145
- merged.configFile = svelteConfig.configFile;
146
- }
147
- return merged;
148
- }
149
-
150
- export async function resolveOptions(
151
- inlineOptions: Partial<Options> = {},
152
- viteConfig: UserConfig,
153
- viteEnv: ConfigEnv
154
- ): Promise<ResolvedOptions> {
155
- const viteConfigWithResolvedRoot = {
156
- ...viteConfig,
157
- root: resolveViteRoot(viteConfig)
158
- };
159
- const svelteConfig = (await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions)) || {};
160
- const defaultOptions = buildDefaultOptions(
161
- viteEnv.mode === 'production',
162
- inlineOptions.emitCss ?? svelteConfig.emitCss
163
- );
164
- const resolvedOptions = mergeOptions(
165
- defaultOptions,
166
- svelteConfig,
167
- inlineOptions,
168
- viteConfigWithResolvedRoot,
169
- viteEnv
170
- );
171
-
172
- enforceOptionsForProduction(resolvedOptions);
173
- enforceOptionsForHmr(resolvedOptions);
174
- return resolvedOptions;
175
- }
176
-
177
177
  // vite passes unresolved `root`option to config hook but we need the resolved value, so do it here
178
178
  // https://github.com/sveltejs/vite-plugin-svelte/issues/113
179
179
  // https://github.com/vitejs/vite/blob/43c957de8a99bb326afd732c962f42127b0a4d1e/packages/vite/src/node/config.ts#L293
@@ -182,7 +182,7 @@ function resolveViteRoot(viteConfig: UserConfig): string | undefined {
182
182
  }
183
183
 
184
184
  export function buildExtraViteConfig(
185
- options: ResolvedOptions,
185
+ options: PreResolvedOptions,
186
186
  config: UserConfig,
187
187
  configEnv: ConfigEnv
188
188
  ): Partial<UserConfig> {
@@ -215,7 +215,7 @@ export function buildExtraViteConfig(
215
215
 
216
216
  function buildOptimizeDepsForSvelte(
217
217
  svelteDeps: SvelteDependency[],
218
- options: ResolvedOptions,
218
+ options: PreResolvedOptions,
219
219
  optimizeDeps?: DepOptimizationOptions
220
220
  ): DepOptimizationOptions {
221
221
  // include svelte imports for optimization unless explicitly excluded
@@ -246,7 +246,7 @@ function buildOptimizeDepsForSvelte(
246
246
  include,
247
247
  exclude,
248
248
  esbuildOptions: {
249
- plugins: [esbuildSveltePlugin(options)]
249
+ plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
250
250
  }
251
251
  };
252
252
  }
@@ -317,6 +317,14 @@ function buildSSROptionsForSvelte(
317
317
  };
318
318
  }
319
319
 
320
+ export function patchResolvedViteConfig(viteConfig: ResolvedConfig, options: ResolvedOptions) {
321
+ const facadeEsbuildSveltePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find(
322
+ (plugin) => plugin.name === facadeEsbuildSveltePluginName
323
+ );
324
+ if (facadeEsbuildSveltePlugin) {
325
+ Object.assign(facadeEsbuildSveltePlugin, esbuildSveltePlugin(options));
326
+ }
327
+ }
320
328
  export interface Options {
321
329
  /**
322
330
  * Path to a svelte config file, either absolute or relative to Vite root
@@ -475,15 +483,18 @@ export interface ExperimentalOptions {
475
483
  }) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
476
484
  }
477
485
 
478
- export interface ResolvedOptions extends Options {
486
+ export interface PreResolvedOptions extends Options {
479
487
  // these options are non-nullable after resolve
480
488
  compilerOptions: CompileOptions;
481
489
  experimental: ExperimentalOptions;
482
490
  // extra options
483
491
  root: string;
484
- isProduction: boolean;
485
492
  isBuild: boolean;
486
493
  isServe: boolean;
494
+ }
495
+
496
+ export interface ResolvedOptions extends PreResolvedOptions {
497
+ isProduction: boolean;
487
498
  server?: ViteDevServer;
488
499
  }
489
500
 
@@ -17,7 +17,6 @@ const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'p
17
17
  const supportedScriptLangs = ['ts'];
18
18
 
19
19
  function createViteScriptPreprocessor(): Preprocessor {
20
- // @ts-expect-error - allow return void
21
20
  return async ({ attributes, content, filename = '' }) => {
22
21
  const lang = attributes.lang as string;
23
22
  if (!supportedScriptLangs.includes(lang)) return;
@@ -26,7 +25,8 @@ function createViteScriptPreprocessor(): Preprocessor {
26
25
  tsconfigRaw: {
27
26
  compilerOptions: {
28
27
  // svelte typescript needs this flag to work with type imports
29
- importsNotUsedAsValues: 'preserve'
28
+ importsNotUsedAsValues: 'preserve',
29
+ preserveValueImports: true
30
30
  }
31
31
  }
32
32
  });
@@ -47,7 +47,6 @@ function createViteStylePreprocessor(config: ResolvedConfig): Preprocessor {
47
47
  throw new Error(`plugin ${pluginName} has no transform`);
48
48
  }
49
49
  const pluginTransform = plugin.transform!.bind(null as unknown as TransformPluginContext);
50
- // @ts-expect-error - allow return void
51
50
  return async ({ attributes, content, filename = '' }) => {
52
51
  const lang = attributes.lang as string;
53
52
  if (!supportedStyleLangs.includes(lang)) return;
@@ -56,20 +55,18 @@ function createViteStylePreprocessor(config: ResolvedConfig): Preprocessor {
56
55
  content,
57
56
  moduleId
58
57
  )) as TransformResult;
59
- // vite returns empty mappings that would kill svelte compiler before 3.43.0
60
- const hasMap = transformResult.map && transformResult.map.mappings !== '';
61
58
  // patch sourcemap source to point back to original filename
62
- if (hasMap && transformResult.map?.sources?.[0] === moduleId) {
59
+ if (transformResult.map?.sources?.[0] === moduleId) {
63
60
  transformResult.map.sources[0] = filename;
64
61
  }
65
62
  return {
66
63
  code: transformResult.code,
67
- map: hasMap ? transformResult.map : undefined
64
+ map: transformResult.map ?? undefined
68
65
  };
69
66
  };
70
67
  }
71
68
 
72
- export function createVitePreprocessorGroup(config: ResolvedConfig): PreprocessorGroup {
69
+ function createVitePreprocessorGroup(config: ResolvedConfig): PreprocessorGroup {
73
70
  return {
74
71
  markup({ content, filename }) {
75
72
  return preprocess(
@@ -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) {
46
+ // in middlewareMode 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();
58
58
  }
59
59
  };
60
60