@sveltejs/vite-plugin-svelte 1.0.0-next.33 → 1.0.0-next.37

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
@@ -19,6 +19,7 @@ import { ensureWatchedFile, setupWatchers } from './utils/watch';
19
19
  import { resolveViaPackageJsonSvelte } from './utils/resolve';
20
20
  import { PartialResolvedId } from 'rollup';
21
21
  import { toRollupError } from './utils/error';
22
+ import { handleOptimizeDeps } from './utils/optimizer';
22
23
 
23
24
  export function svelte(inlineOptions?: Partial<Options>): Plugin {
24
25
  if (process.env.DEBUG != null) {
@@ -26,7 +27,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
26
27
  }
27
28
  validateInlineOptions(inlineOptions);
28
29
  const cache = new VitePluginSvelteCache();
29
- const pkg_export_errors = new Set();
30
+ const pkg_resolve_errors = new Set();
30
31
  // updated in configResolved hook
31
32
  let requestParser: IdParser;
32
33
  let options: ResolvedOptions;
@@ -69,6 +70,10 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
69
70
  log.debug('resolved options', options);
70
71
  },
71
72
 
73
+ async buildStart() {
74
+ await handleOptimizeDeps(options, viteConfig);
75
+ },
76
+
72
77
  configureServer(server) {
73
78
  // eslint-disable-next-line no-unused-vars
74
79
  options.server = server;
@@ -132,21 +137,13 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
132
137
  }
133
138
 
134
139
  try {
135
- const resolved = resolveViaPackageJsonSvelte(importee, importer);
140
+ const resolved = resolveViaPackageJsonSvelte(importee, importer, cache);
136
141
  if (resolved) {
137
142
  log.debug(`resolveId resolved ${resolved} via package.json svelte field of ${importee}`);
138
143
  return resolved;
139
144
  }
140
145
  } catch (err) {
141
- switch (err.code) {
142
- case 'ERR_PACKAGE_PATH_NOT_EXPORTED':
143
- pkg_export_errors.add(importee);
144
- return null;
145
- case 'MODULE_NOT_FOUND':
146
- return null;
147
- default:
148
- throw err;
149
- }
146
+ pkg_resolve_errors.add(importee);
150
147
  }
151
148
  },
152
149
 
@@ -173,7 +170,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
173
170
  try {
174
171
  compileData = await compileSvelte(svelteRequest, code, options);
175
172
  } catch (e) {
176
- throw toRollupError(e);
173
+ throw toRollupError(e, options);
177
174
  }
178
175
  logCompilerWarnings(compileData.compiled.warnings, options);
179
176
  cache.update(compileData);
@@ -201,10 +198,11 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
201
198
  */
202
199
  // TODO generateBundle isn't called by vite, is buildEnd enough or should it be logged once per violation in resolve
203
200
  buildEnd() {
204
- if (pkg_export_errors.size > 0) {
201
+ if (pkg_resolve_errors.size > 0) {
205
202
  log.warn(
206
- `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.`,
207
- 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, '')
208
206
  );
209
207
  }
210
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(
@@ -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
 
@@ -27,7 +27,7 @@ export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
27
27
  const contents = await compileSvelte(options, { filename, code });
28
28
  return { contents };
29
29
  } catch (e) {
30
- return { errors: [toESBuildError(e)] };
30
+ return { errors: [toESBuildError(e, options)] };
31
31
  }
32
32
  });
33
33
  }
@@ -73,7 +73,12 @@ async function compileSvelte(
73
73
  let preprocessed;
74
74
 
75
75
  if (options.preprocess) {
76
- 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
+ }
77
82
  if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
78
83
  }
79
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
+ }
@@ -82,7 +82,8 @@ export async function preResolveOptions(
82
82
  // extras
83
83
  root: viteConfigWithResolvedRoot.root!,
84
84
  isBuild: viteEnv.command === 'build',
85
- isServe: viteEnv.command === 'serve'
85
+ isServe: viteEnv.command === 'serve',
86
+ isDebug: process.env.DEBUG != null
86
87
  };
87
88
  // configFile of svelteConfig contains the absolute path it was loaded from,
88
89
  // prefer it over the possibly relative inline path
@@ -112,6 +113,7 @@ export function resolveOptions(
112
113
  ...defaultOptions.compilerOptions,
113
114
  ...preResolveOptions.compilerOptions
114
115
  },
116
+ root: viteConfig.root,
115
117
  isProduction: viteConfig.isProduction
116
118
  };
117
119
  addExtraPreprocessors(merged, viteConfig);
@@ -490,6 +492,7 @@ export interface PreResolvedOptions extends Options {
490
492
  root: string;
491
493
  isBuild: boolean;
492
494
  isServe: boolean;
495
+ isDebug: boolean;
493
496
  }
494
497
 
495
498
  export interface ResolvedOptions extends PreResolvedOptions {
@@ -25,7 +25,8 @@ function createViteScriptPreprocessor(): Preprocessor {
25
25
  tsconfigRaw: {
26
26
  compilerOptions: {
27
27
  // svelte typescript needs this flag to work with type imports
28
- importsNotUsedAsValues: 'preserve'
28
+ importsNotUsedAsValues: 'preserve',
29
+ preserveValueImports: true
29
30
  }
30
31
  }
31
32
  });
@@ -1,18 +1,42 @@
1
1
  import path from 'path';
2
- import fs from 'fs';
3
- // @ts-ignore
4
- import relative from 'require-relative';
2
+ import { builtinModules, 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 (
12
+ importer &&
13
+ isBareImport(importee) &&
14
+ !isNodeInternal(importee) &&
15
+ !is_common_without_svelte_field(importee)
16
+ ) {
17
+ const cached = cache.getResolvedSvelteField(importee, importer);
18
+ if (cached) {
19
+ return cached;
20
+ }
21
+ const localRequire = createRequire(importer);
22
+ const pkgData = resolveDependencyData(importee, localRequire);
23
+ if (pkgData) {
24
+ const { pkg, dir } = pkgData;
25
+ if (pkg.svelte) {
26
+ const result = path.resolve(dir, pkg.svelte);
27
+ cache.setResolvedSvelteField(importee, importer, result);
28
+ return result;
29
+ }
30
+ } else {
31
+ throw new Error(`failed to resolve package.json of ${importee} imported by ${importer}`);
12
32
  }
13
33
  }
14
34
  }
15
35
 
36
+ function isNodeInternal(importee: string) {
37
+ return importee.startsWith('node:') || builtinModules.includes(importee);
38
+ }
39
+
16
40
  function isBareImport(importee: string): boolean {
17
41
  if (
18
42
  !importee ||
@@ -6,6 +6,7 @@ export class VitePluginSvelteCache {
6
6
  private _js = new Map<string, Code>();
7
7
  private _dependencies = new Map<string, string[]>();
8
8
  private _dependants = new Map<string, Set<string>>();
9
+ private _resolvedSvelteFields = new Map<string, string>();
9
10
 
10
11
  public update(compileData: CompileData) {
11
12
  this.updateCSS(compileData);
@@ -80,4 +81,23 @@ export class VitePluginSvelteCache {
80
81
  const dependants = this._dependants.get(path);
81
82
  return dependants ? [...dependants] : [];
82
83
  }
84
+
85
+ public getResolvedSvelteField(name: string, importer?: string): string | void {
86
+ return this._resolvedSvelteFields.get(this._getResolvedSvelteFieldKey(name, importer));
87
+ }
88
+
89
+ public setResolvedSvelteField(
90
+ importee: string,
91
+ importer: string | undefined = undefined,
92
+ resolvedSvelte: string
93
+ ) {
94
+ this._resolvedSvelteFields.set(
95
+ this._getResolvedSvelteFieldKey(importee, importer),
96
+ resolvedSvelte
97
+ );
98
+ }
99
+
100
+ private _getResolvedSvelteFieldKey(importee: string, importer?: string): string {
101
+ return importer ? `${importer} > ${importee}` : importee;
102
+ }
83
103
  }
@@ -54,7 +54,7 @@ export function setupWatchers(
54
54
  });
55
55
  } else {
56
56
  log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
57
- server.restart(!!options.experimental?.prebundleSvelteLibraries);
57
+ server.restart();
58
58
  }
59
59
  };
60
60