@sveltejs/vite-plugin-svelte 3.0.0-next.1 → 3.0.0-next.3

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/package.json CHANGED
@@ -1,19 +1,21 @@
1
1
  {
2
2
  "name": "@sveltejs/vite-plugin-svelte",
3
- "version": "3.0.0-next.1",
3
+ "version": "3.0.0-next.3",
4
4
  "license": "MIT",
5
5
  "author": "dominikg",
6
6
  "files": [
7
- "src"
7
+ "src",
8
+ "types"
8
9
  ],
9
10
  "type": "module",
10
- "types": "src/index.d.ts",
11
+ "types": "types/index.d.ts",
11
12
  "exports": {
12
13
  ".": {
13
- "types": "./src/index.d.ts",
14
- "import": "./src/index.js"
15
- },
16
- "./package.json": "./package.json"
14
+ "import": {
15
+ "types": "./types/index.d.ts",
16
+ "default": "./src/index.js"
17
+ }
18
+ }
17
19
  },
18
20
  "engines": {
19
21
  "node": "^18.0.0 || >=20"
@@ -43,17 +45,19 @@
43
45
  "vitefu": "^0.2.5"
44
46
  },
45
47
  "peerDependencies": {
46
- "svelte": "^4.0.0",
48
+ "svelte": "^4.0.0 || ^5.0.0-next.0",
47
49
  "vite": "^5.0.0-beta.1 || ^5.0.0"
48
50
  },
49
51
  "devDependencies": {
50
- "@types/debug": "^4.1.9",
51
- "esbuild": "^0.19.4",
52
- "svelte": "^4.2.1",
53
- "vite": "^5.0.0-beta.7"
52
+ "@types/debug": "^4.1.12",
53
+ "esbuild": "^0.19.5",
54
+ "sass": "^1.69.5",
55
+ "svelte": "^4.2.3",
56
+ "vite": "^5.0.0-beta.19"
54
57
  },
55
58
  "scripts": {
56
59
  "check:publint": "publint --strict",
57
- "check:types": "tsc --noEmit"
60
+ "check:types": "tsc --noEmit",
61
+ "generate:types": "dts-buddy -m \"@sveltejs/vite-plugin-svelte:src/public.d.ts\""
58
62
  }
59
63
  }
@@ -7,7 +7,7 @@ import { toRollupError } from './utils/error.js';
7
7
  * @param {Function} compileSvelte
8
8
  * @param {import('vite').HmrContext} ctx
9
9
  * @param {import('./types/id.d.ts').SvelteRequest} svelteRequest
10
- * @param {import('./utils/vite-plugin-svelte-cache').VitePluginSvelteCache} cache
10
+ * @param {import('./utils/vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache
11
11
  * @param {import('./types/options.d.ts').ResolvedOptions} options
12
12
  * @returns {Promise<import('vite').ModuleNode[] | void>}
13
13
  */
package/src/index.js CHANGED
@@ -3,9 +3,9 @@ import fs from 'node:fs';
3
3
  import { svelteInspector } from '@sveltejs/vite-plugin-svelte-inspector';
4
4
 
5
5
  import { handleHotUpdate } from './handle-hot-update.js';
6
- import { log, logCompilerWarnings } from './utils/log.js';
6
+ import { log, logCompilerWarnings, logSvelte5Warning } from './utils/log.js';
7
7
  import { createCompileSvelte } from './utils/compile.js';
8
- import { buildIdParser } from './utils/id.js';
8
+ import { buildIdParser, buildModuleIdParser } from './utils/id.js';
9
9
  import {
10
10
  buildExtraViteConfig,
11
11
  validateInlineOptions,
@@ -19,8 +19,13 @@ import { toRollupError } from './utils/error.js';
19
19
  import { saveSvelteMetadata } from './utils/optimizer.js';
20
20
  import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache.js';
21
21
  import { loadRaw } from './utils/load-raw.js';
22
+ import { isSvelte5 } from './utils/svelte-version.js';
23
+ import * as svelteCompiler from 'svelte/compiler';
22
24
 
23
- /** @type {import('./index.d.ts').svelte} */
25
+ /**
26
+ * @param {Partial<import('./public.d.ts').Options>} [inlineOptions]
27
+ * @returns {import('vite').Plugin[]}
28
+ */
24
29
  export function svelte(inlineOptions) {
25
30
  if (process.env.DEBUG != null) {
26
31
  log.setLevel('debug');
@@ -30,6 +35,8 @@ export function svelte(inlineOptions) {
30
35
  // updated in configResolved hook
31
36
  /** @type {import('./types/id.d.ts').IdParser} */
32
37
  let requestParser;
38
+ /** @type {import('./types/id.d.ts').ModuleIdParser} */
39
+ let moduleRequestParser;
33
40
  /** @type {import('./types/options.d.ts').ResolvedOptions} */
34
41
  let options;
35
42
  /** @type {import('vite').ResolvedConfig} */
@@ -182,9 +189,41 @@ export function svelte(inlineOptions) {
182
189
  async buildEnd() {
183
190
  await options.stats?.finishAll();
184
191
  }
185
- },
186
- svelteInspector()
192
+ }
187
193
  ];
194
+ if (isSvelte5) {
195
+ logSvelte5Warning();
196
+ // TODO move to separate file
197
+ plugins.push({
198
+ name: 'vite-plugin-svelte-module',
199
+ enforce: 'post',
200
+ async configResolved() {
201
+ moduleRequestParser = buildModuleIdParser(options);
202
+ },
203
+ async transform(code, id, opts) {
204
+ const ssr = !!opts?.ssr;
205
+ const moduleRequest = moduleRequestParser(id, ssr);
206
+ if (!moduleRequest) {
207
+ return;
208
+ }
209
+ try {
210
+ // @ts-expect-error compileModule does not exist in svelte4
211
+ const compileResult = await svelteCompiler.compileModule(code, {
212
+ generate: ssr ? 'server' : 'client',
213
+ filename: moduleRequest.filename
214
+ });
215
+ logCompilerWarnings(moduleRequest, compileResult.warnings, options);
216
+ return compileResult.js;
217
+ } catch (e) {
218
+ throw toRollupError(e, options);
219
+ }
220
+ }
221
+ });
222
+ }
223
+ if (!isSvelte5) {
224
+ // TODO reenable once svelte5 has support and update utils/log.js#logSvelte5Warning
225
+ plugins.push(svelteInspector());
226
+ }
188
227
  return plugins;
189
228
  }
190
229
 
package/src/preprocess.js CHANGED
@@ -9,9 +9,12 @@ const supportedScriptLangs = ['ts'];
9
9
 
10
10
  export const lang_sep = '.vite-preprocess';
11
11
 
12
- /** @type {import('./index.d.ts').vitePreprocess} */
12
+ /**
13
+ * @param {import('./public.d.ts').VitePreprocessOptions} opts
14
+ * @returns {import('svelte/compiler').PreprocessorGroup}
15
+ */
13
16
  export function vitePreprocess(opts) {
14
- /** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup} */
17
+ /** @type {import('svelte/compiler').PreprocessorGroup} */
15
18
  const preprocessor = { name: 'vite-preprocess' };
16
19
  if (opts?.script !== false) {
17
20
  preprocessor.script = viteScript().script;
@@ -24,7 +27,7 @@ export function vitePreprocess(opts) {
24
27
  }
25
28
 
26
29
  /**
27
- * @returns {{ script: import('svelte/types/compiler/preprocess').Preprocessor }}
30
+ * @returns {{ script: import('svelte/compiler').Preprocessor }}
28
31
  */
29
32
  function viteScript() {
30
33
  return {
@@ -55,12 +58,12 @@ function viteScript() {
55
58
 
56
59
  /**
57
60
  * @param {import('vite').ResolvedConfig | import('vite').InlineConfig} config
58
- * @returns {{ style: import('svelte/types/compiler/preprocess').Preprocessor }}
61
+ * @returns {{ style: import('svelte/compiler').Preprocessor }}
59
62
  */
60
63
  function viteStyle(config = {}) {
61
64
  /** @type {CssTransform} */
62
65
  let transform;
63
- /** @type {import('svelte/types/compiler/preprocess').Preprocessor} */
66
+ /** @type {import('svelte/compiler').Preprocessor} */
64
67
  const style = async ({ attributes, content, filename = '' }) => {
65
68
  const ext = attributes.lang ? `.${attributes.lang}` : '.css';
66
69
  if (attributes.lang && !isCSSRequest(ext)) return;
@@ -1,9 +1,10 @@
1
- import type { InlineConfig, ResolvedConfig, UserConfig, Plugin } from 'vite';
2
- import type { CompileOptions, Warning } from 'svelte/types/compiler/interfaces';
3
- import type { PreprocessorGroup } from 'svelte/types/compiler/preprocess';
1
+ import type { InlineConfig, ResolvedConfig } from 'vite';
2
+ import type { CompileOptions } from 'svelte/compiler';
3
+ import type { Warning } from 'svelte/types/compiler/interfaces';
4
+ import type { PreprocessorGroup } from 'svelte/compiler';
4
5
  import type { Options as InspectorOptions } from '@sveltejs/vite-plugin-svelte-inspector';
5
6
 
6
- type Options = Omit<SvelteOptions, 'vitePlugin'> & PluginOptionsInline;
7
+ export type Options = Omit<SvelteConfig, 'vitePlugin'> & PluginOptionsInline;
7
8
 
8
9
  interface PluginOptionsInline extends PluginOptions {
9
10
  /**
@@ -94,13 +95,39 @@ interface PluginOptions {
94
95
  * @default unset for dev, always false for build
95
96
  */
96
97
  inspector?: InspectorOptions | boolean;
98
+
99
+ /**
100
+ * A function to update `compilerOptions` before compilation
101
+ *
102
+ * `data.filename` - The file to be compiled
103
+ * `data.code` - The preprocessed Svelte code
104
+ * `data.compileOptions` - The current compiler options
105
+ *
106
+ * To change part of the compiler options, return an object with the changes you need.
107
+ *
108
+ * @example
109
+ * ```
110
+ * ({ filename, compileOptions }) => {
111
+ * // Dynamically set hydration per Svelte file
112
+ * if (compileWithHydratable(filename) && !compileOptions.hydratable) {
113
+ * return { hydratable: true };
114
+ * }
115
+ * }
116
+ * ```
117
+ */
118
+ dynamicCompileOptions?: (data: {
119
+ filename: string;
120
+ code: string;
121
+ compileOptions: Partial<CompileOptions>;
122
+ }) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
123
+
97
124
  /**
98
125
  * These options are considered experimental and breaking changes to them can occur in any release
99
126
  */
100
127
  experimental?: ExperimentalOptions;
101
128
  }
102
129
 
103
- interface SvelteOptions {
130
+ export interface SvelteConfig {
104
131
  /**
105
132
  * A list of file extensions to be compiled by Svelte
106
133
  *
@@ -122,31 +149,6 @@ interface SvelteOptions {
122
149
  */
123
150
  compilerOptions?: Omit<CompileOptions, 'filename' | 'format' | 'generate'>;
124
151
 
125
- /**
126
- * A function to update `compilerOptions` before compilation
127
- *
128
- * `data.filename` - The file to be compiled
129
- * `data.code` - The preprocessed Svelte code
130
- * `data.compileOptions` - The current compiler options
131
- *
132
- * To change part of the compiler options, return an object with the changes you need.
133
- *
134
- * @example
135
- * ```
136
- * ({ filename, compileOptions }) => {
137
- * // Dynamically set hydration per Svelte file
138
- * if (compileWithHydratable(filename) && !compileOptions.hydratable) {
139
- * return { hydratable: true };
140
- * }
141
- * }
142
- * ```
143
- */
144
- dynamicCompileOptions?: (data: {
145
- filename: string;
146
- code: string;
147
- compileOptions: Partial<CompileOptions>;
148
- }) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
149
-
150
152
  /**
151
153
  * Handles warning emitted from the Svelte compiler
152
154
  */
@@ -172,46 +174,21 @@ interface ExperimentalOptions {
172
174
  * @default false
173
175
  */
174
176
  disableSvelteResolveWarnings?: boolean;
177
+
178
+ compileModule?: CompileModuleOptions;
179
+ }
180
+
181
+ interface CompileModuleOptions {
182
+ extensions?: string[];
183
+ include?: Arrayable<string>;
184
+ exclude?: Arrayable<string>;
175
185
  }
176
186
 
177
- type ModuleFormat = NonNullable<'esm'>;
178
- type CssHashGetter = NonNullable<CompileOptions['cssHash']>;
179
187
  type Arrayable<T> = T | T[];
180
188
 
181
- interface VitePreprocessOptions {
189
+ export interface VitePreprocessOptions {
182
190
  script?: boolean;
183
191
  style?: boolean | InlineConfig | ResolvedConfig;
184
192
  }
185
193
 
186
- declare function vitePreprocess(opts?: VitePreprocessOptions): PreprocessorGroup;
187
-
188
- declare function loadSvelteConfig(
189
- viteConfig?: UserConfig,
190
- inlineOptions?: Partial<Options>
191
- ): Promise<Partial<SvelteOptions> | undefined>;
192
-
193
- declare function svelte(inlineOptions?: Partial<Options>): Plugin[];
194
-
195
- export {
196
- Arrayable,
197
- CssHashGetter,
198
- ModuleFormat,
199
- Options,
200
- PluginOptions,
201
- SvelteOptions,
202
- loadSvelteConfig,
203
- svelte,
204
- VitePreprocessOptions,
205
- vitePreprocess
206
- };
207
-
208
- // reexported types
209
-
210
- export { CompileOptions, Warning } from 'svelte/types/compiler/interfaces';
211
-
212
- export {
213
- MarkupPreprocessor,
214
- Preprocessor,
215
- PreprocessorGroup,
216
- Processed
217
- } from 'svelte/types/compiler/preprocess';
194
+ export * from './index.js';
@@ -1,4 +1,4 @@
1
- import type { Processed } from 'svelte/types/compiler/preprocess';
1
+ import type { Processed, CompileResult } from 'svelte/compiler';
2
2
  import type { SvelteRequest } from './id.d.ts';
3
3
  import type { ResolvedOptions } from './options.d.ts';
4
4
 
@@ -14,34 +14,11 @@ export interface Code {
14
14
  dependencies?: any[];
15
15
  }
16
16
 
17
- export interface Compiled {
18
- js: Code;
19
- css: Code;
20
- ast: any; // TODO type
21
- warnings: any[]; // TODO type
22
- vars: Array<{
23
- name: string;
24
- export_name: string;
25
- injected: boolean;
26
- module: boolean;
27
- mutated: boolean;
28
- reassigned: boolean;
29
- referenced: boolean;
30
- writable: boolean;
31
- referenced_from_script: boolean;
32
- }>;
33
- stats: {
34
- timings: {
35
- total: number;
36
- };
37
- };
38
- }
39
-
40
17
  export interface CompileData {
41
18
  filename: string;
42
19
  normalizedFilename: string;
43
20
  lang: string;
44
- compiled: Compiled;
21
+ compiled: CompileResult;
45
22
  ssr: boolean | undefined;
46
23
  dependencies: string[];
47
24
  preprocessed: Processed;
package/src/types/id.d.ts CHANGED
@@ -28,4 +28,18 @@ export interface SvelteRequest {
28
28
  raw: boolean;
29
29
  }
30
30
 
31
+ export interface SvelteModuleRequest {
32
+ id: string;
33
+ filename: string;
34
+ normalizedFilename: string;
35
+ query: RequestQuery;
36
+ timestamp: number;
37
+ ssr: boolean;
38
+ }
39
+
31
40
  export type IdParser = (id: string, ssr: boolean, timestamp?: number) => SvelteRequest | undefined;
41
+ export type ModuleIdParser = (
42
+ id: string,
43
+ ssr: boolean,
44
+ timestamp?: number
45
+ ) => SvelteModuleRequest | undefined;
@@ -1,4 +1,4 @@
1
- import type { Warning } from '../index.d.ts';
1
+ import type { Warning } from 'svelte/types/compiler/interfaces';
2
2
 
3
3
  export interface LogFn extends SimpleLogFn {
4
4
  (message: string, payload?: any, namespace?: string): void;
@@ -1,7 +1,7 @@
1
1
  import type { CompileOptions } from 'svelte/types/compiler/interfaces';
2
2
  import type { ViteDevServer } from 'vite';
3
3
  import { VitePluginSvelteStats } from '../utils/vite-plugin-svelte-stats.js';
4
- import type { Options } from '../index.d.ts';
4
+ import type { Options } from '../public.d.ts';
5
5
 
6
6
  export interface PreResolvedOptions extends Options {
7
7
  // these options are non-nullable after resolve
@@ -1,4 +1,4 @@
1
- import { compile, preprocess, walk } from 'svelte/compiler';
1
+ import * as svelte from 'svelte/compiler';
2
2
  // @ts-ignore
3
3
  import { createMakeHot } from 'svelte-hmr';
4
4
  import { safeBase64Hash } from './hash.js';
@@ -10,6 +10,7 @@ import {
10
10
  } from './preprocess.js';
11
11
  import { mapToRelative } from './sourcemaps.js';
12
12
  import { enhanceCompileError } from './error.js';
13
+ import { isSvelte5 } from './svelte-version.js';
13
14
 
14
15
  const scriptLangRE = /<script [^>]*lang=["']?([^"' >]+)["']?[^>]*>/;
15
16
 
@@ -54,11 +55,12 @@ export const _createCompileSvelte = (makeHot) => {
54
55
  // also they for hmr updates too
55
56
  }
56
57
  }
57
- /** @type {import('../index.d.ts').CompileOptions} */
58
+ /** @type {import('svelte/compiler').CompileOptions} */
58
59
  const compileOptions = {
59
60
  ...options.compilerOptions,
60
61
  filename,
61
- generate: ssr ? 'ssr' : 'dom'
62
+ // @ts-expect-error svelte5 uses server/client, svelte4 uses ssr/dom
63
+ generate: isSvelte5 ? (ssr ? 'server' : 'client') : ssr ? 'ssr' : 'dom'
62
64
  };
63
65
 
64
66
  if (options.hot && options.emitCss) {
@@ -87,7 +89,7 @@ export const _createCompileSvelte = (makeHot) => {
87
89
  }
88
90
  if (preprocessors) {
89
91
  try {
90
- preprocessed = await preprocess(code, preprocessors, { filename }); // full filename here so postcss works
92
+ preprocessed = await svelte.preprocess(code, preprocessors, { filename }); // full filename here so postcss works
91
93
  } catch (e) {
92
94
  e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;
93
95
  throw e;
@@ -138,7 +140,7 @@ export const _createCompileSvelte = (makeHot) => {
138
140
  /** @type {import('svelte/types/compiler/interfaces').CompileResult} */
139
141
  let compiled;
140
142
  try {
141
- compiled = compile(finalCode, finalCompileOptions);
143
+ compiled = svelte.compile(finalCode, finalCompileOptions);
142
144
  } catch (e) {
143
145
  enhanceCompileError(e, code, preprocessors);
144
146
  throw e;
@@ -203,7 +205,7 @@ function buildMakeHot(options) {
203
205
  // @ts-ignore
204
206
  const adapter = options?.hot?.adapter;
205
207
  return createMakeHot({
206
- walk,
208
+ walk: svelte.walk,
207
209
  hotApi,
208
210
  adapter,
209
211
  hotOptions: { noOverlay: true, .../** @type {object} */ (options.hot) }
@@ -1,3 +1,5 @@
1
+ import { isSvelte5 } from './svelte-version.js';
2
+
1
3
  export const VITE_RESOLVE_MAIN_FIELDS = ['module', 'jsnext:main', 'jsnext'];
2
4
 
3
5
  export const SVELTE_RESOLVE_MAIN_FIELDS = ['svelte'];
@@ -20,6 +22,11 @@ export const SVELTE_HMR_IMPORTS = [
20
22
  'svelte-hmr'
21
23
  ];
22
24
 
25
+ if (isSvelte5) {
26
+ SVELTE_IMPORTS.push('svelte/server', 'svelte/internal/server', 'svelte/legacy');
27
+ SVELTE_HMR_IMPORTS.length = 0; // truncate, svelte-hmr isn't used with svelte5
28
+ }
29
+
23
30
  export const SVELTE_EXPORT_CONDITIONS = ['svelte'];
24
31
 
25
32
  export const FAQ_LINK_MISSING_EXPORTS_CONDITION =
@@ -104,7 +104,7 @@ function formatFrameForVite(frame) {
104
104
  /**
105
105
  * @param {import('svelte/types/compiler/interfaces').Warning & Error} err a svelte compiler error, which is a mix of Warning and an error
106
106
  * @param {string} originalCode
107
- * @param {import('../index.js').Arrayable<import('svelte/types/compiler/preprocess').PreprocessorGroup>} [preprocessors]
107
+ * @param {import('../public.d.ts').Options['preprocess']} [preprocessors]
108
108
  */
109
109
  export function enhanceCompileError(err, originalCode, preprocessors) {
110
110
  preprocessors = arraify(preprocessors ?? []);
@@ -1,7 +1,8 @@
1
1
  import { readFileSync } from 'node:fs';
2
- import { compile, preprocess } from 'svelte/compiler';
2
+ import * as svelte from 'svelte/compiler';
3
3
  import { log } from './log.js';
4
4
  import { toESBuildError } from './error.js';
5
+ import { isSvelte5 } from './svelte-version.js';
5
6
 
6
7
  /**
7
8
  * @typedef {NonNullable<import('vite').DepOptimizationOptions['esbuildOptions']>} EsbuildOptions
@@ -10,6 +11,8 @@ import { toESBuildError } from './error.js';
10
11
 
11
12
  export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade';
12
13
 
14
+ const svelteModuleExtension = '.svelte.js';
15
+
13
16
  /**
14
17
  * @param {import('../types/options.d.ts').ResolvedOptions} options
15
18
  * @returns {EsbuildPlugin}
@@ -23,6 +26,9 @@ export function esbuildSveltePlugin(options) {
23
26
  if (build.initialOptions.plugins?.some((v) => v.name === 'vite:dep-scan')) return;
24
27
 
25
28
  const svelteExtensions = (options.extensions ?? ['.svelte']).map((ext) => ext.slice(1));
29
+ if (isSvelte5) {
30
+ svelteExtensions.push(svelteModuleExtension.slice(1));
31
+ }
26
32
  const svelteFilter = new RegExp('\\.(' + svelteExtensions.join('|') + ')(\\?.*)?$');
27
33
  /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
28
34
  let statsCollection;
@@ -54,24 +60,39 @@ export function esbuildSveltePlugin(options) {
54
60
  * @returns {Promise<string>}
55
61
  */
56
62
  async function compileSvelte(options, { filename, code }, statsCollection) {
63
+ if (isSvelte5 && filename.endsWith(svelteModuleExtension)) {
64
+ const endStat = statsCollection?.start(filename);
65
+ // @ts-expect-error compileModule does not exist in svelte4
66
+ const compiled = svelte.compileModule(code, {
67
+ filename,
68
+ generate: 'client'
69
+ });
70
+ if (endStat) {
71
+ endStat();
72
+ }
73
+ return compiled.js.map
74
+ ? compiled.js.code + '//# sourceMappingURL=' + compiled.js.map.toUrl()
75
+ : compiled.js.code;
76
+ }
57
77
  let css = options.compilerOptions.css;
58
78
  if (css !== 'none') {
59
79
  // TODO ideally we'd be able to externalize prebundled styles too, but for now always put them in the js
60
80
  css = 'injected';
61
81
  }
62
- /** @type {import('../index.d.ts').CompileOptions} */
82
+ /** @type {import('svelte/compiler').CompileOptions} */
63
83
  const compileOptions = {
64
84
  ...options.compilerOptions,
65
85
  css,
66
86
  filename,
67
- generate: 'dom'
87
+ // @ts-expect-error svelte4 uses 'dom', svelte5 uses 'client'
88
+ generate: isSvelte5 ? 'client' : 'dom'
68
89
  };
69
90
 
70
91
  let preprocessed;
71
92
 
72
93
  if (options.preprocess) {
73
94
  try {
74
- preprocessed = await preprocess(code, options.preprocess, { filename });
95
+ preprocessed = await svelte.preprocess(code, options.preprocess, { filename });
75
96
  } catch (e) {
76
97
  e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;
77
98
  throw e;
@@ -102,7 +123,7 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
102
123
  }
103
124
  : compileOptions;
104
125
  const endStat = statsCollection?.start(filename);
105
- const compiled = compile(finalCode, finalCompileOptions);
126
+ const compiled = svelte.compile(finalCode, finalCompileOptions);
106
127
  if (endStat) {
107
128
  endStat();
108
129
  }
package/src/utils/id.js CHANGED
@@ -159,8 +159,8 @@ function stripRoot(normalizedFilename, normalizedRoot) {
159
159
  }
160
160
 
161
161
  /**
162
- * @param {import('../index.d.ts').Arrayable<string> | undefined} include
163
- * @param {import('../index.d.ts').Arrayable<string> | undefined} exclude
162
+ * @param {import('../public.d.ts').Options['include'] | undefined} include
163
+ * @param {import('../public.d.ts').Options['exclude'] | undefined} exclude
164
164
  * @param {string[]} extensions
165
165
  * @returns {(filename: string) => boolean}
166
166
  */
@@ -184,3 +184,49 @@ export function buildIdParser(options) {
184
184
  }
185
185
  };
186
186
  }
187
+
188
+ /**
189
+ * @param {import('../types/options.d.ts').ResolvedOptions} options
190
+ * @returns {import('../types/id.d.ts').ModuleIdParser}
191
+ */
192
+ export function buildModuleIdParser(options) {
193
+ const { include, exclude, extensions } = options?.experimental?.compileModule ?? {};
194
+ const root = options.root;
195
+ const normalizedRoot = normalizePath(root);
196
+ const filter = buildFilter(include, exclude, extensions ?? ['.svelte.js', '.svelte.ts']);
197
+ return (id, ssr, timestamp = Date.now()) => {
198
+ const { filename, rawQuery } = splitId(id);
199
+ if (filter(filename)) {
200
+ return parseToSvelteModuleRequest(id, filename, rawQuery, normalizedRoot, timestamp, ssr);
201
+ }
202
+ };
203
+ }
204
+
205
+ /**
206
+ * @param {string} id
207
+ * @param {string} filename
208
+ * @param {string} rawQuery
209
+ * @param {string} root
210
+ * @param {number} timestamp
211
+ * @param {boolean} ssr
212
+ * @returns {import('../types/id.d.ts').SvelteModuleRequest | undefined}
213
+ */
214
+ function parseToSvelteModuleRequest(id, filename, rawQuery, root, timestamp, ssr) {
215
+ const query = parseRequestQuery(rawQuery);
216
+
217
+ if (query.url || query.raw || query.direct) {
218
+ // skip requests with special vite tags
219
+ return;
220
+ }
221
+
222
+ const normalizedFilename = normalize(filename, root);
223
+
224
+ return {
225
+ id,
226
+ filename,
227
+ normalizedFilename,
228
+ query,
229
+ timestamp,
230
+ ssr
231
+ };
232
+ }
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import { toRollupError } from './error.js';
3
3
  import { log } from './log.js';
4
-
4
+ import { isSvelte4 } from './svelte-version.js';
5
5
  /**
6
6
  * utility function to compile ?raw and ?direct requests in load hook
7
7
  *
@@ -18,15 +18,15 @@ export async function loadRaw(svelteRequest, compileSvelte, options) {
18
18
  const source = fs.readFileSync(filename, 'utf-8');
19
19
  try {
20
20
  //avoid compileSvelte doing extra ssr stuff unless requested
21
- svelteRequest.ssr = query.compilerOptions?.generate === 'ssr';
21
+ //@ts-ignore //@ts-expect-error generate value differs between svelte4 and 5
22
+ svelteRequest.ssr = query.compilerOptions?.generate === (isSvelte4 ? 'ssr' : 'server');
22
23
  const type = query.type;
23
24
  compileData = await compileSvelte(svelteRequest, source, {
24
25
  ...options,
25
26
  // don't use dynamic vite-plugin-svelte defaults here to ensure stable result between ssr,dev and build
26
27
  compilerOptions: {
27
28
  dev: false,
28
- css: false,
29
- hydratable: false,
29
+ css: 'external',
30
30
  enableSourcemap: query.sourcemap
31
31
  ? {
32
32
  js: type === 'script' || type === 'all',
@@ -16,16 +16,19 @@ export const knownSvelteConfigNames = [
16
16
  'svelte.config.mjs'
17
17
  ];
18
18
 
19
- // hide dynamic import from ts transform to prevent it turning into a require
20
- // see https://github.com/microsoft/TypeScript/issues/43329#issuecomment-811606238
21
- // also use timestamp query to avoid caching on reload
22
- const dynamicImportDefault = new Function(
23
- 'path',
24
- 'timestamp',
25
- 'return import(path + "?t=" + timestamp).then(m => m.default)'
26
- );
19
+ /**
20
+ * @param {string} filePath
21
+ * @param {number} timestamp
22
+ */
23
+ async function dynamicImportDefault(filePath, timestamp) {
24
+ return await import(filePath + '?t=' + timestamp).then((m) => m.default);
25
+ }
27
26
 
28
- /** @type {import('../index.d.ts').loadSvelteConfig} */
27
+ /**
28
+ * @param {import('vite').UserConfig} viteConfig
29
+ * @param {Partial<import('../public.d.ts').Options>} inlineOptions
30
+ * @returns {Promise<Partial<import('../public.d.ts').SvelteConfig> | undefined>}
31
+ */
29
32
  export async function loadSvelteConfig(viteConfig, inlineOptions) {
30
33
  if (inlineOptions?.configFile === false) {
31
34
  return;
@@ -87,7 +90,7 @@ export async function loadSvelteConfig(viteConfig, inlineOptions) {
87
90
 
88
91
  /**
89
92
  * @param {import('vite').UserConfig | undefined} viteConfig
90
- * @param {Partial<import('../index.d.ts').Options> | undefined} inlineOptions
93
+ * @param {Partial<import('../public.d.ts').Options> | undefined} inlineOptions
91
94
  * @returns {string | undefined}
92
95
  */
93
96
  function findConfigToLoad(viteConfig, inlineOptions) {
package/src/utils/log.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable no-console */
2
2
  import { cyan, red, yellow } from 'kleur/colors';
3
3
  import debug from 'debug';
4
+ import { VERSION } from 'svelte/compiler';
4
5
 
5
6
  /** @type {import('../types/log.d.ts').LogLevel[]} */
6
7
  const levels = ['debug', 'info', 'warn', 'error', 'silent'];
@@ -126,7 +127,7 @@ export const log = {
126
127
  };
127
128
 
128
129
  /**
129
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
130
+ * @param {import('../types/id.d.ts').SvelteRequest | import('../types/id.d.ts').SvelteModuleRequest} svelteRequest
130
131
  * @param {import('svelte/types/compiler/interfaces').Warning[]} warnings
131
132
  * @param {import('../types/options.d.ts').ResolvedOptions} options
132
133
  */
@@ -259,3 +260,12 @@ export function buildExtendedLogMessage(w) {
259
260
  export function isDebugNamespaceEnabled(namespace) {
260
261
  return debug.enabled(`${prefix}:${namespace}`);
261
262
  }
263
+
264
+ export function logSvelte5Warning() {
265
+ const notice = `Your are using Svelte ${VERSION}. Svelte 5 support is experimental, breaking changes can occur in any release until this notice is removed.`;
266
+ const wip = [
267
+ 'svelte-inspector is disabled until dev mode implements node to code mapping',
268
+ 'hmr for .svelte files is disabled until hmr api is implemented'
269
+ ];
270
+ log.warn(`${notice}\nwork in progress:\n - ${wip.join('\n - ')}\n`);
271
+ }
@@ -26,6 +26,7 @@ import {
26
26
  import { isCommonDepWithoutSvelteField } from './dependencies.js';
27
27
  import { VitePluginSvelteStats } from './vite-plugin-svelte-stats.js';
28
28
  import { VitePluginSvelteCache } from './vite-plugin-svelte-cache.js';
29
+ import { isSvelte5 } from './svelte-version.js';
29
30
 
30
31
  const allowedPluginOptions = new Set([
31
32
  'include',
@@ -45,7 +46,7 @@ const knownRootOptions = new Set(['extensions', 'compilerOptions', 'preprocess',
45
46
  const allowedInlineOptions = new Set(['configFile', ...allowedPluginOptions, ...knownRootOptions]);
46
47
 
47
48
  /**
48
- * @param {Partial<import('../index.d.ts').Options>} [inlineOptions]
49
+ * @param {Partial<import('../public.d.ts').Options>} [inlineOptions]
49
50
  */
50
51
  export function validateInlineOptions(inlineOptions) {
51
52
  const invalidKeys = Object.keys(inlineOptions || {}).filter(
@@ -57,8 +58,8 @@ export function validateInlineOptions(inlineOptions) {
57
58
  }
58
59
 
59
60
  /**
60
- * @param {Partial<import('../index.d.ts').SvelteOptions>} [config]
61
- * @returns {Partial<import('../index.d.ts').Options> | undefined}
61
+ * @param {Partial<import('../public.d.ts').SvelteConfig>} [config]
62
+ * @returns {Partial<import('../public.d.ts').Options> | undefined}
62
63
  */
63
64
  function convertPluginOptions(config) {
64
65
  if (!config) {
@@ -108,7 +109,7 @@ function convertPluginOptions(config) {
108
109
  delete pluginOptions[unkownOption];
109
110
  });
110
111
  }
111
- /** @type {import('../index.d.ts').Options} */
112
+ /** @type {import('../public.d.ts').Options} */
112
113
  const result = {
113
114
  ...config,
114
115
  ...pluginOptions
@@ -121,7 +122,7 @@ function convertPluginOptions(config) {
121
122
 
122
123
  /**
123
124
  * used in config phase, merges the default options, svelte config, and inline options
124
- * @param {Partial<import('../index.d.ts').Options> | undefined} inlineOptions
125
+ * @param {Partial<import('../public.d.ts').Options> | undefined} inlineOptions
125
126
  * @param {import('vite').UserConfig} viteUserConfig
126
127
  * @param {import('vite').ConfigEnv} viteEnv
127
128
  * @returns {Promise<import('../types/options.d.ts').PreResolvedOptions>}
@@ -191,7 +192,7 @@ function mergeConfigs(...configs) {
191
192
  */
192
193
  export function resolveOptions(preResolveOptions, viteConfig, cache) {
193
194
  const css = preResolveOptions.emitCss ? 'external' : 'injected';
194
- /** @type {Partial<import('../index.d.ts').Options>} */
195
+ /** @type {Partial<import('../public.d.ts').Options>} */
195
196
  const defaultOptions = {
196
197
  hot: viteConfig.isProduction
197
198
  ? false
@@ -229,6 +230,10 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
229
230
  * @param {import('../types/options.d.ts').ResolvedOptions} options
230
231
  */
231
232
  function enforceOptionsForHmr(options) {
233
+ if (isSvelte5) {
234
+ // TODO add hmr options for svelte5 once it is supported and update utils/log.js#logSvelte5Warning
235
+ options.hot = false;
236
+ }
232
237
  if (options.hot) {
233
238
  if (!options.compilerOptions.dev) {
234
239
  log.warn('hmr is enabled but compilerOptions.dev is false, forcing it to true');
@@ -9,7 +9,7 @@ import { normalizePath } from 'vite';
9
9
  *
10
10
  * only used during dev with enabled css hmr
11
11
  *
12
- * @returns {import('svelte/types/compiler/preprocess').PreprocessorGroup}
12
+ * @returns {import('svelte/compiler').PreprocessorGroup}
13
13
  */
14
14
  export function createInjectScopeEverythingRulePreprocessorGroup() {
15
15
  return {
@@ -32,14 +32,14 @@ export function createInjectScopeEverythingRulePreprocessorGroup() {
32
32
  * @param {import('../types/options.d.ts').ResolvedOptions} options
33
33
  * @param {import('vite').ResolvedConfig} config
34
34
  * @returns {{
35
- * prependPreprocessors: import('svelte/types/compiler/preprocess').PreprocessorGroup[],
36
- * appendPreprocessors: import('svelte/types/compiler/preprocess').PreprocessorGroup[]
35
+ * prependPreprocessors: import('svelte/compiler').PreprocessorGroup[],
36
+ * appendPreprocessors: import('svelte/compiler').PreprocessorGroup[]
37
37
  * }}
38
38
  */
39
39
  function buildExtraPreprocessors(options, config) {
40
- /** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup[]} */
40
+ /** @type {import('svelte/compiler').PreprocessorGroup[]} */
41
41
  const prependPreprocessors = [];
42
- /** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup[]} */
42
+ /** @type {import('svelte/compiler').PreprocessorGroup[]} */
43
43
  const appendPreprocessors = [];
44
44
 
45
45
  // @ts-ignore
@@ -3,4 +3,9 @@ import { VERSION } from 'svelte/compiler';
3
3
  /**
4
4
  * @type {boolean}
5
5
  */
6
- export const isSvelte3 = VERSION.startsWith('3.');
6
+ export const isSvelte4 = VERSION.startsWith('4.');
7
+
8
+ /**
9
+ * @type {boolean}
10
+ */
11
+ export const isSvelte5 = VERSION.startsWith('5.');
@@ -5,7 +5,7 @@ import path from 'node:path';
5
5
 
6
6
  /**
7
7
  * @param {import('../types/options.d.ts').ResolvedOptions} options
8
- * @param {import('./vite-plugin-svelte-cache').VitePluginSvelteCache} cache
8
+ * @param {import('./vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache
9
9
  * @param {import('../types/id.d.ts').IdParser} requestParser
10
10
  * @returns {void}
11
11
  */
@@ -0,0 +1,197 @@
1
+ declare module '@sveltejs/vite-plugin-svelte' {
2
+ import type { InlineConfig, ResolvedConfig } from 'vite';
3
+ import type { CompileOptions, PreprocessorGroup } from 'svelte/compiler';
4
+ import type { Warning } from 'svelte/types/compiler/interfaces';
5
+ import type { Options as InspectorOptions } from '@sveltejs/vite-plugin-svelte-inspector';
6
+ export type Options = Omit<SvelteConfig, 'vitePlugin'> & PluginOptionsInline;
7
+
8
+ interface PluginOptionsInline extends PluginOptions {
9
+ /**
10
+ * Path to a svelte config file, either absolute or relative to Vite root
11
+ *
12
+ * set to `false` to ignore the svelte config file
13
+ *
14
+ * @see https://vitejs.dev/config/#root
15
+ */
16
+ configFile?: string | false;
17
+ }
18
+
19
+ interface PluginOptions {
20
+ /**
21
+ * A `picomatch` pattern, or array of patterns, which specifies the files the plugin should
22
+ * operate on. By default, all svelte files are included.
23
+ *
24
+ * @see https://github.com/micromatch/picomatch
25
+ */
26
+ include?: Arrayable<string>;
27
+ /**
28
+ * A `picomatch` pattern, or array of patterns, which specifies the files to be ignored by the
29
+ * plugin. By default, no files are ignored.
30
+ *
31
+ * @see https://github.com/micromatch/picomatch
32
+ */
33
+ exclude?: Arrayable<string>;
34
+ /**
35
+ * Emit Svelte styles as virtual CSS files for Vite and other plugins to process
36
+ *
37
+ * @default true
38
+ */
39
+ emitCss?: boolean;
40
+ /**
41
+ * Enable or disable Hot Module Replacement.
42
+ *
43
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
44
+ *
45
+ * DO NOT CUSTOMIZE SVELTE-HMR OPTIONS UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING
46
+ *
47
+ * YOU HAVE BEEN WARNED
48
+ *
49
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50
+ *
51
+ * Set an object to pass custom options to svelte-hmr
52
+ *
53
+ * @see https://github.com/rixo/svelte-hmr#options
54
+ * @default true for development, always false for production
55
+ */
56
+ hot?:
57
+ | boolean
58
+ | {
59
+ injectCss?: boolean;
60
+ partialAccept?: boolean;
61
+ [key: string]: any;
62
+ };
63
+ /**
64
+ * Some Vite plugins can contribute additional preprocessors by defining `api.sveltePreprocess`.
65
+ * If you don't want to use them, set this to true to ignore them all or use an array of strings
66
+ * with plugin names to specify which.
67
+ *
68
+ * @default false
69
+ */
70
+ ignorePluginPreprocessors?: boolean | string[];
71
+ /**
72
+ * vite-plugin-svelte automatically handles excluding svelte libraries and reinclusion of their dependencies
73
+ * in vite.optimizeDeps.
74
+ *
75
+ * `disableDependencyReinclusion: true` disables all reinclusions
76
+ * `disableDependencyReinclusion: ['foo','bar']` disables reinclusions for dependencies of foo and bar
77
+ *
78
+ * This should be used for hybrid packages that contain both node and browser dependencies, eg Routify
79
+ *
80
+ * @default false
81
+ */
82
+ disableDependencyReinclusion?: boolean | string[];
83
+ /**
84
+ * Enable support for Vite's dependency optimization to prebundle Svelte libraries.
85
+ *
86
+ * To disable prebundling for a specific library, add it to `optimizeDeps.exclude`.
87
+ *
88
+ * @default true for dev, false for build
89
+ */
90
+ prebundleSvelteLibraries?: boolean;
91
+ /**
92
+ * toggle/configure Svelte Inspector
93
+ *
94
+ * @default unset for dev, always false for build
95
+ */
96
+ inspector?: InspectorOptions | boolean;
97
+
98
+ /**
99
+ * A function to update `compilerOptions` before compilation
100
+ *
101
+ * `data.filename` - The file to be compiled
102
+ * `data.code` - The preprocessed Svelte code
103
+ * `data.compileOptions` - The current compiler options
104
+ *
105
+ * To change part of the compiler options, return an object with the changes you need.
106
+ *
107
+ * @example
108
+ * ```
109
+ * ({ filename, compileOptions }) => {
110
+ * // Dynamically set hydration per Svelte file
111
+ * if (compileWithHydratable(filename) && !compileOptions.hydratable) {
112
+ * return { hydratable: true };
113
+ * }
114
+ * }
115
+ * ```
116
+ */
117
+ dynamicCompileOptions?: (data: {
118
+ filename: string;
119
+ code: string;
120
+ compileOptions: Partial<CompileOptions>;
121
+ }) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
122
+
123
+ /**
124
+ * These options are considered experimental and breaking changes to them can occur in any release
125
+ */
126
+ experimental?: ExperimentalOptions;
127
+ }
128
+
129
+ export interface SvelteConfig {
130
+ /**
131
+ * A list of file extensions to be compiled by Svelte
132
+ *
133
+ * @default ['.svelte']
134
+ */
135
+ extensions?: string[];
136
+ /**
137
+ * An array of preprocessors to transform the Svelte source code before compilation
138
+ *
139
+ * @see https://svelte.dev/docs#svelte_preprocess
140
+ */
141
+ preprocess?: Arrayable<PreprocessorGroup>;
142
+ /**
143
+ * The options to be passed to the Svelte compiler. A few options are set by default,
144
+ * including `dev` and `css`. However, some options are non-configurable, like
145
+ * `filename`, `format`, `generate`, and `cssHash` (in dev).
146
+ *
147
+ * @see https://svelte.dev/docs#svelte_compile
148
+ */
149
+ compilerOptions?: Omit<CompileOptions, 'filename' | 'format' | 'generate'>;
150
+
151
+ /**
152
+ * Handles warning emitted from the Svelte compiler
153
+ */
154
+ onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void;
155
+ /**
156
+ * Options for vite-plugin-svelte
157
+ */
158
+ vitePlugin?: PluginOptions;
159
+ }
160
+
161
+ /**
162
+ * These options are considered experimental and breaking changes to them can occur in any release
163
+ */
164
+ interface ExperimentalOptions {
165
+ /**
166
+ * send a websocket message with svelte compiler warnings during dev
167
+ *
168
+ */
169
+ sendWarningsToBrowser?: boolean;
170
+ /**
171
+ * disable svelte field resolve warnings
172
+ *
173
+ * @default false
174
+ */
175
+ disableSvelteResolveWarnings?: boolean;
176
+
177
+ compileModule?: CompileModuleOptions;
178
+ }
179
+
180
+ interface CompileModuleOptions {
181
+ extensions?: string[];
182
+ include?: Arrayable<string>;
183
+ exclude?: Arrayable<string>;
184
+ }
185
+
186
+ type Arrayable<T> = T | T[];
187
+
188
+ export interface VitePreprocessOptions {
189
+ script?: boolean;
190
+ style?: boolean | InlineConfig | ResolvedConfig;
191
+ }
192
+ export function svelte(inlineOptions?: Partial<Options> | undefined): import('vite').Plugin[];
193
+ export function vitePreprocess(opts: VitePreprocessOptions): import('svelte/compiler').PreprocessorGroup;
194
+ export function loadSvelteConfig(viteConfig: import('vite').UserConfig, inlineOptions: Partial<Options>): Promise<Partial<SvelteConfig> | undefined>;
195
+ }
196
+
197
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,25 @@
1
+ {
2
+ "version": 3,
3
+ "file": "index.d.ts",
4
+ "names": [
5
+ "Options",
6
+ "SvelteConfig",
7
+ "VitePreprocessOptions",
8
+ "svelte",
9
+ "vitePreprocess",
10
+ "loadSvelteConfig"
11
+ ],
12
+ "sources": [
13
+ "../src/public.d.ts",
14
+ "../src/index.js",
15
+ "../src/preprocess.js",
16
+ "../src/utils/load-svelte-config.js"
17
+ ],
18
+ "sourcesContent": [
19
+ null,
20
+ null,
21
+ null,
22
+ null
23
+ ],
24
+ "mappings": ";;;;;aAMYA,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA2HFC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA2DZC,qBAAqBA;;;;iBChKtBC,MAAMA;iBCbNC,cAAcA;iBCgBRC,gBAAgBA"
25
+ }