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

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,15 +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';
20
21
  import { toRollupError } from './utils/error';
22
+ import { handleOptimizeDeps } from './utils/optimizer';
21
23
 
22
24
  export function svelte(inlineOptions?: Partial<Options>): Plugin {
23
25
  if (process.env.DEBUG != null) {
@@ -25,7 +27,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
25
27
  }
26
28
  validateInlineOptions(inlineOptions);
27
29
  const cache = new VitePluginSvelteCache();
28
- const pkg_export_errors = new Set();
30
+ const pkg_resolve_errors = new Set();
29
31
  // updated in configResolved hook
30
32
  let requestParser: IdParser;
31
33
  let options: ResolvedOptions;
@@ -51,21 +53,27 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
51
53
  } else if (config.logLevel) {
52
54
  log.setLevel(config.logLevel);
53
55
  }
54
- 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);
55
58
  // extra vite config
56
59
  const extraViteConfig = buildExtraViteConfig(options, config, configEnv);
57
60
  log.debug('additional vite config', extraViteConfig);
58
- return extraViteConfig as Partial<UserConfig>;
61
+ return extraViteConfig;
59
62
  },
60
63
 
61
64
  async configResolved(config) {
62
- addExtraPreprocessors(options, config);
65
+ options = resolveOptions(options, config);
66
+ patchResolvedViteConfig(config, options);
63
67
  requestParser = buildIdParser(options);
64
68
  compileSvelte = createCompileSvelte(options);
65
69
  viteConfig = config;
66
70
  log.debug('resolved options', options);
67
71
  },
68
72
 
73
+ async buildStart() {
74
+ await handleOptimizeDeps(options, viteConfig);
75
+ },
76
+
69
77
  configureServer(server) {
70
78
  // eslint-disable-next-line no-unused-vars
71
79
  options.server = server;
@@ -129,21 +137,13 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
129
137
  }
130
138
 
131
139
  try {
132
- const resolved = resolveViaPackageJsonSvelte(importee, importer);
140
+ const resolved = resolveViaPackageJsonSvelte(importee, importer, cache);
133
141
  if (resolved) {
134
142
  log.debug(`resolveId resolved ${resolved} via package.json svelte field of ${importee}`);
135
143
  return resolved;
136
144
  }
137
145
  } catch (err) {
138
- switch (err.code) {
139
- case 'ERR_PACKAGE_PATH_NOT_EXPORTED':
140
- pkg_export_errors.add(importee);
141
- return null;
142
- case 'MODULE_NOT_FOUND':
143
- return null;
144
- default:
145
- throw err;
146
- }
146
+ pkg_resolve_errors.add(importee);
147
147
  }
148
148
  },
149
149
 
@@ -170,7 +170,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
170
170
  try {
171
171
  compileData = await compileSvelte(svelteRequest, code, options);
172
172
  } catch (e) {
173
- throw toRollupError(e);
173
+ throw toRollupError(e, options);
174
174
  }
175
175
  logCompilerWarnings(compileData.compiled.warnings, options);
176
176
  cache.update(compileData);
@@ -198,10 +198,11 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
198
198
  */
199
199
  // TODO generateBundle isn't called by vite, is buildEnd enough or should it be logged once per violation in resolve
200
200
  buildEnd() {
201
- if (pkg_export_errors.size > 0) {
201
+ if (pkg_resolve_errors.size > 0) {
202
202
  log.warn(
203
- `The following packages did not export their \`package.json\` file so we could not check the "svelte" field. If you had difficulties importing svelte components from a package, then please contact the author and ask them to export the package.json file.`,
204
- Array.from(pkg_export_errors, (s) => `- ${s}`).join('\n')
203
+ `vite-plugin-svelte was unable to find package.json of the following packages and wasn't able to resolve via their "svelte" field.
204
+ If you had difficulties importing svelte components from a package, then please contact the author and ask them to export the package.json file.
205
+ ${Array.from(pkg_resolve_errors, (s) => `- ${s}`).join('\n')}`.replace(/\t/g, '')
205
206
  );
206
207
  }
207
208
  }
@@ -37,7 +37,13 @@ const _createCompileSvelte = (makeHot: Function) =>
37
37
  let preprocessed;
38
38
 
39
39
  if (options.preprocess) {
40
- preprocessed = await preprocess(code, options.preprocess, { filename });
40
+ try {
41
+ preprocessed = await preprocess(code, options.preprocess, { filename });
42
+ } catch (e) {
43
+ e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;
44
+ throw e;
45
+ }
46
+
41
47
  if (preprocessed.dependencies) dependencies.push(...preprocessed.dependencies);
42
48
  if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
43
49
  }
@@ -66,7 +66,10 @@ function getSvelteDependencies(
66
66
  return result;
67
67
  }
68
68
 
69
- function resolveDependencyData(dep: string, localRequire: NodeRequire): DependencyData | void {
69
+ export function resolveDependencyData(
70
+ dep: string,
71
+ localRequire: NodeRequire
72
+ ): DependencyData | void {
70
73
  try {
71
74
  const pkgJson = `${dep}/package.json`;
72
75
  const pkg = localRequire(pkgJson);
@@ -166,7 +169,7 @@ const COMMON_PREFIXES_WITHOUT_SVELTE_FIELD = [
166
169
  * @param dependency {string}
167
170
  * @returns {boolean} true if it is a dependency without a svelte field
168
171
  */
169
- function is_common_without_svelte_field(dependency: string): boolean {
172
+ export function is_common_without_svelte_field(dependency: string): boolean {
170
173
  return (
171
174
  COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD.includes(dependency) ||
172
175
  COMMON_PREFIXES_WITHOUT_SVELTE_FIELD.some(
@@ -184,7 +187,12 @@ export function needsOptimization(dep: string, localRequire: NodeRequire): boole
184
187
  const pkg = depData.pkg;
185
188
  // only optimize if is cjs, using the below as heuristic
186
189
  // see https://github.com/sveltejs/vite-plugin-svelte/issues/162
187
- return pkg.main && !pkg.module && !pkg.exports;
190
+ const isCjs = pkg.main && !pkg.module && !pkg.exports;
191
+ if (!isCjs) return false;
192
+ // ensure entry is js so vite can prebundle it
193
+ // see https://github.com/sveltejs/vite-plugin-svelte/issues/233
194
+ const entryExt = path.extname(pkg.main);
195
+ return !entryExt || entryExt === '.js' || entryExt === '.cjs';
188
196
  }
189
197
 
190
198
  interface DependencyData {
@@ -1,5 +1,5 @@
1
1
  import { RollupError } from 'rollup';
2
- import { Warning } from './options';
2
+ import { ResolvedOptions, Warning } from './options';
3
3
  import { buildExtendedLogMessage } from './log';
4
4
  import { PartialMessage } from 'esbuild';
5
5
 
@@ -8,15 +8,15 @@ import { PartialMessage } from 'esbuild';
8
8
  * @param error a svelte compiler error, which is a mix of Warning and an error
9
9
  * @returns {RollupError} the converted error
10
10
  */
11
- export function toRollupError(error: Warning & Error): RollupError {
12
- const { filename, frame, start, code, name } = error;
11
+ export function toRollupError(error: Warning & Error, options: ResolvedOptions): RollupError {
12
+ const { filename, frame, start, code, name, stack } = error;
13
13
  const rollupError: RollupError = {
14
14
  name, // needed otherwise sveltekit coalesce_to_error turns it into a string
15
15
  id: filename,
16
16
  message: buildExtendedLogMessage(error), // include filename:line:column so that it's clickable
17
17
  frame: formatFrameForVite(frame),
18
18
  code,
19
- stack: ''
19
+ stack: options.isBuild || options.isDebug || !frame ? stack : ''
20
20
  };
21
21
  if (start) {
22
22
  rollupError.loc = {
@@ -33,8 +33,8 @@ export function toRollupError(error: Warning & Error): RollupError {
33
33
  * @param error a svelte compiler error, which is a mix of Warning and an error
34
34
  * @returns {PartialMessage} the converted error
35
35
  */
36
- export function toESBuildError(error: Warning & Error): PartialMessage {
37
- const { filename, frame, start } = error;
36
+ export function toESBuildError(error: Warning & Error, options: ResolvedOptions): PartialMessage {
37
+ const { filename, frame, start, stack } = error;
38
38
  const partialMessage: PartialMessage = {
39
39
  text: buildExtendedLogMessage(error)
40
40
  };
@@ -46,6 +46,9 @@ export function toESBuildError(error: Warning & Error): PartialMessage {
46
46
  lineText: lineFromFrame(start.line, frame) // needed to get a meaningful error message on cli
47
47
  };
48
48
  }
49
+ if (options.isBuild || options.isDebug || !frame) {
50
+ partialMessage.detail = stack;
51
+ }
49
52
  return partialMessage;
50
53
  }
51
54
 
@@ -10,6 +10,8 @@ type EsbuildOptions = NonNullable<DepOptimizationOptions['esbuildOptions']>;
10
10
  type EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];
11
11
  type EsbuildPluginBuild = Parameters<EsbuildPlugin['setup']>[0];
12
12
 
13
+ export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade';
14
+
13
15
  export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
14
16
  return {
15
17
  name: 'vite-plugin-svelte:optimize-svelte',
@@ -25,7 +27,7 @@ export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
25
27
  const contents = await compileSvelte(options, { filename, code });
26
28
  return { contents };
27
29
  } catch (e) {
28
- return { errors: [toESBuildError(e)] };
30
+ return { errors: [toESBuildError(e, options)] };
29
31
  }
30
32
  });
31
33
  }
@@ -64,13 +66,19 @@ async function compileSvelte(
64
66
  ...options.compilerOptions,
65
67
  css: true,
66
68
  filename,
69
+ format: 'esm',
67
70
  generate: 'dom'
68
71
  };
69
72
 
70
73
  let preprocessed;
71
74
 
72
75
  if (options.preprocess) {
73
- preprocessed = await preprocess(code, options.preprocess, { filename });
76
+ try {
77
+ preprocessed = await preprocess(code, options.preprocess, { filename });
78
+ } catch (e) {
79
+ e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;
80
+ throw e;
81
+ }
74
82
  if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
75
83
  }
76
84
 
package/src/utils/log.ts CHANGED
@@ -164,7 +164,10 @@ export function buildExtendedLogMessage(w: Warning) {
164
164
  parts.push(':', w.start.line, ':', w.start.column);
165
165
  }
166
166
  if (w.message) {
167
- parts.push(' ', w.message);
167
+ if (parts.length > 0) {
168
+ parts.push(' ');
169
+ }
170
+ parts.push(w.message);
168
171
  }
169
172
  return parts.join('');
170
173
  }
@@ -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,86 @@ 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
+ isDebug: process.env.DEBUG != null
87
+ };
88
+ // configFile of svelteConfig contains the absolute path it was loaded from,
89
+ // prefer it over the possibly relative inline path
90
+ if (svelteConfig?.configFile) {
91
+ merged.configFile = svelteConfig.configFile;
92
+ }
93
+ return merged;
55
94
  }
56
95
 
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
- }
96
+ // used in configResolved phase, merges a contextual default config, pre-resolved options, and some preprocessors.
97
+ // also validates the final config.
98
+ export function resolveOptions(
99
+ preResolveOptions: PreResolvedOptions,
100
+ viteConfig: ResolvedConfig
101
+ ): ResolvedOptions {
102
+ const defaultOptions: Partial<Options> = {
103
+ hot: viteConfig.isProduction ? false : { injectCss: !preResolveOptions.emitCss },
104
+ compilerOptions: {
105
+ css: !preResolveOptions.emitCss,
106
+ dev: !viteConfig.isProduction
107
+ }
108
+ };
109
+ const merged: ResolvedOptions = {
110
+ ...defaultOptions,
111
+ ...preResolveOptions,
112
+ compilerOptions: {
113
+ ...defaultOptions.compilerOptions,
114
+ ...preResolveOptions.compilerOptions
115
+ },
116
+ root: viteConfig.root,
117
+ isProduction: viteConfig.isProduction
118
+ };
119
+ addExtraPreprocessors(merged, viteConfig);
120
+ enforceOptionsForHmr(merged);
121
+ enforceOptionsForProduction(merged);
122
+ return merged;
62
123
  }
63
124
 
64
125
  function enforceOptionsForHmr(options: ResolvedOptions) {
@@ -114,69 +175,6 @@ function enforceOptionsForProduction(options: ResolvedOptions) {
114
175
  }
115
176
  }
116
177
 
117
- function mergeOptions(
118
- defaultOptions: Partial<Options>,
119
- svelteConfig: Partial<Options>,
120
- inlineOptions: Partial<Options>,
121
- viteConfig: UserConfig,
122
- viteEnv: ConfigEnv
123
- ): ResolvedOptions {
124
- // @ts-ignore
125
- const merged = {
126
- ...defaultOptions,
127
- ...svelteConfig,
128
- ...inlineOptions,
129
- compilerOptions: {
130
- ...defaultOptions.compilerOptions,
131
- ...(svelteConfig?.compilerOptions || {}),
132
- ...(inlineOptions?.compilerOptions || {})
133
- },
134
- experimental: {
135
- ...(svelteConfig?.experimental || {}),
136
- ...(inlineOptions?.experimental || {})
137
- },
138
- root: viteConfig.root!,
139
- isProduction: viteEnv.mode === 'production',
140
- isBuild: viteEnv.command === 'build',
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
144
- };
145
- // configFile of svelteConfig contains the absolute path it was loaded from,
146
- // prefer it over the possibly relative inline path
147
- if (svelteConfig?.configFile) {
148
- merged.configFile = svelteConfig.configFile;
149
- }
150
- return merged;
151
- }
152
-
153
- export async function resolveOptions(
154
- inlineOptions: Partial<Options> = {},
155
- viteConfig: UserConfig,
156
- viteEnv: ConfigEnv
157
- ): Promise<ResolvedOptions> {
158
- const viteConfigWithResolvedRoot = {
159
- ...viteConfig,
160
- root: resolveViteRoot(viteConfig)
161
- };
162
- const svelteConfig = (await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions)) || {};
163
- const defaultOptions = buildDefaultOptions(
164
- viteEnv.mode === 'production',
165
- inlineOptions.emitCss ?? svelteConfig.emitCss
166
- );
167
- const resolvedOptions = mergeOptions(
168
- defaultOptions,
169
- svelteConfig,
170
- inlineOptions,
171
- viteConfigWithResolvedRoot,
172
- viteEnv
173
- );
174
-
175
- enforceOptionsForProduction(resolvedOptions);
176
- enforceOptionsForHmr(resolvedOptions);
177
- return resolvedOptions;
178
- }
179
-
180
178
  // vite passes unresolved `root`option to config hook but we need the resolved value, so do it here
181
179
  // https://github.com/sveltejs/vite-plugin-svelte/issues/113
182
180
  // https://github.com/vitejs/vite/blob/43c957de8a99bb326afd732c962f42127b0a4d1e/packages/vite/src/node/config.ts#L293
@@ -185,7 +183,7 @@ function resolveViteRoot(viteConfig: UserConfig): string | undefined {
185
183
  }
186
184
 
187
185
  export function buildExtraViteConfig(
188
- options: ResolvedOptions,
186
+ options: PreResolvedOptions,
189
187
  config: UserConfig,
190
188
  configEnv: ConfigEnv
191
189
  ): Partial<UserConfig> {
@@ -218,7 +216,7 @@ export function buildExtraViteConfig(
218
216
 
219
217
  function buildOptimizeDepsForSvelte(
220
218
  svelteDeps: SvelteDependency[],
221
- options: ResolvedOptions,
219
+ options: PreResolvedOptions,
222
220
  optimizeDeps?: DepOptimizationOptions
223
221
  ): DepOptimizationOptions {
224
222
  // include svelte imports for optimization unless explicitly excluded
@@ -249,7 +247,7 @@ function buildOptimizeDepsForSvelte(
249
247
  include,
250
248
  exclude,
251
249
  esbuildOptions: {
252
- plugins: [esbuildSveltePlugin(options)]
250
+ plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
253
251
  }
254
252
  };
255
253
  }
@@ -320,6 +318,14 @@ function buildSSROptionsForSvelte(
320
318
  };
321
319
  }
322
320
 
321
+ export function patchResolvedViteConfig(viteConfig: ResolvedConfig, options: ResolvedOptions) {
322
+ const facadeEsbuildSveltePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find(
323
+ (plugin) => plugin.name === facadeEsbuildSveltePluginName
324
+ );
325
+ if (facadeEsbuildSveltePlugin) {
326
+ Object.assign(facadeEsbuildSveltePlugin, esbuildSveltePlugin(options));
327
+ }
328
+ }
323
329
  export interface Options {
324
330
  /**
325
331
  * Path to a svelte config file, either absolute or relative to Vite root
@@ -478,17 +484,20 @@ export interface ExperimentalOptions {
478
484
  }) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
479
485
  }
480
486
 
481
- export interface ResolvedOptions extends Options {
487
+ export interface PreResolvedOptions extends Options {
482
488
  // these options are non-nullable after resolve
483
489
  compilerOptions: CompileOptions;
484
490
  experimental: ExperimentalOptions;
485
491
  // extra options
486
492
  root: string;
487
- isProduction: boolean;
488
493
  isBuild: boolean;
489
494
  isServe: boolean;
495
+ isDebug: boolean;
496
+ }
497
+
498
+ export interface ResolvedOptions extends PreResolvedOptions {
499
+ isProduction: boolean;
490
500
  server?: ViteDevServer;
491
- isSvelteKit?: boolean;
492
501
  }
493
502
 
494
503
  export type {
@@ -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(
@@ -1,14 +1,29 @@
1
1
  import path from 'path';
2
- import fs from 'fs';
3
- // @ts-ignore
4
- import relative from 'require-relative';
2
+ import { createRequire } from 'module';
3
+ import { is_common_without_svelte_field, resolveDependencyData } from './dependencies';
4
+ import { VitePluginSvelteCache } from './vite-plugin-svelte-cache';
5
5
 
6
- export function resolveViaPackageJsonSvelte(importee: string, importer?: string): string | void {
7
- if (importer && isBareImport(importee)) {
8
- const importeePkgFile = relative.resolve(`${importee}/package.json`, path.dirname(importer));
9
- const importeePkg = JSON.parse(fs.readFileSync(importeePkgFile, { encoding: 'utf-8' }));
10
- if (importeePkg.svelte) {
11
- return path.resolve(path.dirname(importeePkgFile), importeePkg.svelte);
6
+ export function resolveViaPackageJsonSvelte(
7
+ importee: string,
8
+ importer: string | undefined,
9
+ cache: VitePluginSvelteCache
10
+ ): string | void {
11
+ if (importer && isBareImport(importee) && !is_common_without_svelte_field(importee)) {
12
+ const cached = cache.getResolvedSvelteField(importee, importer);
13
+ if (cached) {
14
+ return cached;
15
+ }
16
+ const localRequire = createRequire(importer);
17
+ const pkgData = resolveDependencyData(importee, localRequire);
18
+ if (pkgData) {
19
+ const { pkg, dir } = pkgData;
20
+ if (pkg.svelte) {
21
+ const result = path.resolve(dir, pkg.svelte);
22
+ cache.setResolvedSvelteField(importee, importer, result);
23
+ return result;
24
+ }
25
+ } else {
26
+ throw new Error(`failed to resolve package.json of ${importee} imported by ${importer}`);
12
27
  }
13
28
  }
14
29
  }