@sveltejs/vite-plugin-svelte 3.1.0 → 4.0.0-next.1

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/vite-plugin-svelte",
3
- "version": "3.1.0",
3
+ "version": "4.0.0-next.1",
4
4
  "license": "MIT",
5
5
  "author": "dominikg",
6
6
  "files": [
@@ -18,7 +18,7 @@
18
18
  }
19
19
  },
20
20
  "engines": {
21
- "node": "^18.0.0 || >=20"
21
+ "node": "^18.0.0 || ^20.0.0 || >=22"
22
22
  },
23
23
  "repository": {
24
24
  "type": "git",
@@ -36,24 +36,23 @@
36
36
  },
37
37
  "homepage": "https://github.com/sveltejs/vite-plugin-svelte#readme",
38
38
  "dependencies": {
39
- "@sveltejs/vite-plugin-svelte-inspector": "^2.0.0",
40
39
  "debug": "^4.3.4",
41
40
  "deepmerge": "^4.3.1",
42
41
  "kleur": "^4.1.5",
43
- "magic-string": "^0.30.9",
44
- "svelte-hmr": "^0.16.0",
45
- "vitefu": "^0.2.5"
42
+ "magic-string": "^0.30.10",
43
+ "vitefu": "^0.2.5",
44
+ "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.1"
46
45
  },
47
46
  "peerDependencies": {
48
- "svelte": "^4.0.0 || ^5.0.0-next.0",
47
+ "svelte": "^5.0.0-next.96 || ^5.0.0",
49
48
  "vite": "^5.0.0"
50
49
  },
51
50
  "devDependencies": {
52
51
  "@types/debug": "^4.1.12",
53
52
  "esbuild": "^0.20.2",
54
- "sass": "^1.74.1",
55
- "svelte": "^4.2.12",
56
- "vite": "^5.2.8"
53
+ "sass": "^1.76.0",
54
+ "svelte": "^5.0.0-next.123",
55
+ "vite": "^5.2.11"
57
56
  },
58
57
  "scripts": {
59
58
  "check:publint": "publint --strict",
@@ -81,8 +81,8 @@ export async function handleHotUpdate(compileSvelte, ctx, svelteRequest, cache,
81
81
  }
82
82
 
83
83
  /**
84
- * @param {import('./types/compile.d.ts').Code} [prev]
85
- * @param {import('./types/compile.d.ts').Code} [next]
84
+ * @param {import('./types/compile.d.ts').Code | null} [prev]
85
+ * @param {import('./types/compile.d.ts').Code | null} [next]
86
86
  * @returns {boolean}
87
87
  */
88
88
  function cssChanged(prev, next) {
@@ -90,8 +90,8 @@ function cssChanged(prev, next) {
90
90
  }
91
91
 
92
92
  /**
93
- * @param {import('./types/compile.d.ts').Code} [prev]
94
- * @param {import('./types/compile.d.ts').Code} [next]
93
+ * @param {import('./types/compile.d.ts').Code | null} [prev]
94
+ * @param {import('./types/compile.d.ts').Code | null} [next]
95
95
  * @param {string} [filename]
96
96
  * @returns {boolean}
97
97
  */
package/src/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  import fs from 'node:fs';
2
-
3
2
  import { svelteInspector } from '@sveltejs/vite-plugin-svelte-inspector';
4
-
5
3
  import { handleHotUpdate } from './handle-hot-update.js';
6
- import { log, logCompilerWarnings, logSvelte5Warning } from './utils/log.js';
4
+ import { log, logCompilerWarnings } from './utils/log.js';
7
5
  import { createCompileSvelte } from './utils/compile.js';
8
6
  import { buildIdParser, buildModuleIdParser } from './utils/id.js';
9
7
  import {
@@ -13,13 +11,11 @@ import {
13
11
  patchResolvedViteConfig,
14
12
  preResolveOptions
15
13
  } from './utils/options.js';
16
-
17
14
  import { ensureWatchedFile, setupWatchers } from './utils/watch.js';
18
15
  import { toRollupError } from './utils/error.js';
19
16
  import { saveSvelteMetadata } from './utils/optimizer.js';
20
17
  import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache.js';
21
18
  import { loadRaw } from './utils/load-raw.js';
22
- import { isSvelte5 } from './utils/svelte-version.js';
23
19
  import * as svelteCompiler from 'svelte/compiler';
24
20
 
25
21
  /**
@@ -72,7 +68,7 @@ export function svelte(inlineOptions) {
72
68
  options = resolveOptions(options, config, cache);
73
69
  patchResolvedViteConfig(config, options);
74
70
  requestParser = buildIdParser(options);
75
- compileSvelte = createCompileSvelte(options);
71
+ compileSvelte = createCompileSvelte();
76
72
  viteConfig = config;
77
73
  // TODO deep clone to avoid mutability from outside?
78
74
  api.options = options;
@@ -178,8 +174,7 @@ export function svelte(inlineOptions) {
178
174
  },
179
175
 
180
176
  handleHotUpdate(ctx) {
181
- // @ts-expect-error svelte4 does not have hmr option
182
- if ((!options.hot && !options.compilerOptions.hmr) || !options.emitCss) {
177
+ if (!options.compilerOptions.hmr || !options.emitCss) {
183
178
  return;
184
179
  }
185
180
  const svelteRequest = requestParser(ctx.file, false, ctx.timestamp);
@@ -190,12 +185,8 @@ export function svelte(inlineOptions) {
190
185
  async buildEnd() {
191
186
  await options.stats?.finishAll();
192
187
  }
193
- }
194
- ];
195
- if (isSvelte5) {
196
- logSvelte5Warning();
197
- // TODO move to separate file
198
- plugins.push({
188
+ },
189
+ {
199
190
  name: 'vite-plugin-svelte-module',
200
191
  enforce: 'post',
201
192
  async configResolved() {
@@ -208,8 +199,8 @@ export function svelte(inlineOptions) {
208
199
  return;
209
200
  }
210
201
  try {
211
- // @ts-expect-error compileModule does not exist in svelte4
212
- const compileResult = await svelteCompiler.compileModule(code, {
202
+ const compileResult = svelteCompiler.compileModule(code, {
203
+ dev: !viteConfig.isProduction,
213
204
  generate: ssr ? 'server' : 'client',
214
205
  filename: moduleRequest.filename
215
206
  });
@@ -219,12 +210,9 @@ export function svelte(inlineOptions) {
219
210
  throw toRollupError(e, options);
220
211
  }
221
212
  }
222
- });
223
- }
224
- if (!isSvelte5) {
225
- // TODO reenable once svelte5 has support and update utils/log.js#logSvelte5Warning
226
- plugins.push(svelteInspector());
227
- }
213
+ },
214
+ svelteInspector()
215
+ ];
228
216
  return plugins;
229
217
  }
230
218
 
package/src/preprocess.js CHANGED
@@ -16,7 +16,7 @@ export const lang_sep = '.vite-preprocess';
16
16
  export function vitePreprocess(opts) {
17
17
  /** @type {import('svelte/compiler').PreprocessorGroup} */
18
18
  const preprocessor = { name: 'vite-preprocess' };
19
- if (opts?.script !== false) {
19
+ if (opts?.script === true) {
20
20
  preprocessor.script = viteScript().script;
21
21
  }
22
22
  if (opts?.style !== false) {
package/src/public.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { InlineConfig, ResolvedConfig } from 'vite';
2
2
  import type { CompileOptions } from 'svelte/compiler';
3
- import type { Warning } from 'svelte/types/compiler/interfaces';
3
+ import type { Warning } from 'svelte/compiler';
4
4
  import type { PreprocessorGroup } from 'svelte/compiler';
5
5
  import type { Options as InspectorOptions } from '@sveltejs/vite-plugin-svelte-inspector';
6
6
 
@@ -40,27 +40,13 @@ interface PluginOptions {
40
40
  emitCss?: boolean;
41
41
  /**
42
42
  * Enable or disable Hot Module Replacement.
43
+ * Deprecated, use compilerOptions.hmr instead!
43
44
  *
44
- * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
45
- *
46
- * DO NOT CUSTOMIZE SVELTE-HMR OPTIONS UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING
47
- *
48
- * YOU HAVE BEEN WARNED
49
- *
50
- * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
51
- *
52
- * Set an object to pass custom options to svelte-hmr
53
- *
54
- * @see https://github.com/rixo/svelte-hmr#options
45
+ * @deprecated
55
46
  * @default true for development, always false for production
56
47
  */
57
- hot?:
58
- | boolean
59
- | {
60
- injectCss?: boolean;
61
- partialAccept?: boolean;
62
- [key: string]: any;
63
- };
48
+ hot?: boolean;
49
+
64
50
  /**
65
51
  * Some Vite plugins can contribute additional preprocessors by defining `api.sveltePreprocess`.
66
52
  * If you don't want to use them, set this to true to ignore them all or use an array of strings
@@ -151,8 +137,18 @@ export interface SvelteConfig {
151
137
 
152
138
  /**
153
139
  * Handles warning emitted from the Svelte compiler
140
+ *
141
+ * @example
142
+ * ```
143
+ * (warning, defaultHandler) => {
144
+ * // ignore some warnings
145
+ * if (!['foo','bar'].includes(warning.code)) {
146
+ * defaultHandler(warning);
147
+ * }
148
+ * }
149
+ * ```
154
150
  */
155
- onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void;
151
+ onwarn?: (warning: Warning, defaultHandler: (warning: Warning) => void) => void;
156
152
  /**
157
153
  * Options for vite-plugin-svelte
158
154
  */
@@ -179,6 +175,15 @@ interface ExperimentalOptions {
179
175
  }
180
176
 
181
177
  interface CompileModuleOptions {
178
+ /**
179
+ * infix that must be present in filename
180
+ * @default ['.svelte.']
181
+ */
182
+ infixes?: string[];
183
+ /**
184
+ * module extensions
185
+ * @default ['.ts','.js']
186
+ */
182
187
  extensions?: string[];
183
188
  include?: Arrayable<string>;
184
189
  exclude?: Arrayable<string>;
@@ -187,7 +192,16 @@ interface CompileModuleOptions {
187
192
  type Arrayable<T> = T | T[];
188
193
 
189
194
  export interface VitePreprocessOptions {
195
+ /**
196
+ * preprocess script block with vite pipeline.
197
+ * Since svelte5 this is not needed for typescript anymore
198
+ *
199
+ * @default false
200
+ */
190
201
  script?: boolean;
202
+ /**
203
+ * preprocess style blocks with vite pipeline
204
+ */
191
205
  style?: boolean | InlineConfig | ResolvedConfig;
192
206
  }
193
207
 
package/src/types/id.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { CompileOptions } from 'svelte/types/compiler/interfaces';
1
+ import type { CompileOptions } from 'svelte/compiler';
2
2
 
3
3
  export type SvelteQueryTypes = 'style' | 'script' | 'preprocessed' | 'all';
4
4
 
@@ -9,7 +9,7 @@ export interface RequestQuery {
9
9
  sourcemap?: boolean;
10
10
  compilerOptions?: Pick<
11
11
  CompileOptions,
12
- 'generate' | 'dev' | 'css' | 'hydratable' | 'customElement' | 'immutable' | 'enableSourcemap'
12
+ 'generate' | 'dev' | 'css' | 'customElement' | 'immutable'
13
13
  >;
14
14
  // vite specific
15
15
  url?: boolean;
@@ -1,4 +1,4 @@
1
- import type { Warning } from 'svelte/types/compiler/interfaces';
1
+ import type { Warning } from 'svelte/compiler';
2
2
 
3
3
  export interface LogFn extends SimpleLogFn {
4
4
  (message: string, payload?: any, namespace?: string): void;
@@ -1,4 +1,4 @@
1
- import type { CompileOptions } from 'svelte/types/compiler/interfaces';
1
+ import type { CompileOptions } from 'svelte/compiler';
2
2
  import type { ViteDevServer } from 'vite';
3
3
  import { VitePluginSvelteStats } from '../utils/vite-plugin-svelte-stats.js';
4
4
  import type { Options } from '../public.d.ts';
@@ -1,6 +1,5 @@
1
1
  import * as svelte from 'svelte/compiler';
2
- // @ts-ignore
3
- import { createMakeHot } from 'svelte-hmr';
2
+
4
3
  import { safeBase64Hash } from './hash.js';
5
4
  import { log } from './log.js';
6
5
 
@@ -10,7 +9,6 @@ import {
10
9
  } from './preprocess.js';
11
10
  import { mapToRelative } from './sourcemaps.js';
12
11
  import { enhanceCompileError } from './error.js';
13
- import { isSvelte5 } from './svelte-version.js';
14
12
 
15
13
  // TODO this is a patched version of https://github.com/sveltejs/vite-plugin-svelte/pull/796/files#diff-3bce0b33034aad4b35ca094893671f7e7ddf4d27254ae7b9b0f912027a001b15R10
16
14
  // which is closer to the other regexes in at least not falling into commented script
@@ -19,10 +17,9 @@ const scriptLangRE =
19
17
  /<!--[^]*?-->|<script (?:[^>]*|(?:[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)\s+)*)lang=["']?([^"' >]+)["']?[^>]*>/g;
20
18
 
21
19
  /**
22
- * @param {Function} [makeHot]
23
20
  * @returns {import('../types/compile.d.ts').CompileSvelte}
24
21
  */
25
- export const _createCompileSvelte = (makeHot) => {
22
+ export function createCompileSvelte() {
26
23
  /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
27
24
  let stats;
28
25
  const devStylePreprocessor = createInjectScopeEverythingRulePreprocessorGroup();
@@ -32,7 +29,7 @@ export const _createCompileSvelte = (makeHot) => {
32
29
  const { emitCss = true } = options;
33
30
  /** @type {string[]} */
34
31
  const dependencies = [];
35
- /** @type {import('svelte/types/compiler/interfaces').Warning[]} */
32
+ /** @type {import('svelte/compiler').Warning[]} */
36
33
  const warnings = [];
37
34
 
38
35
  if (options.stats) {
@@ -63,18 +60,17 @@ export const _createCompileSvelte = (makeHot) => {
63
60
  const compileOptions = {
64
61
  ...options.compilerOptions,
65
62
  filename,
66
- // @ts-expect-error svelte5 uses server/client, svelte4 uses ssr/dom
67
- generate: isSvelte5 ? (ssr ? 'server' : 'client') : ssr ? 'ssr' : 'dom'
63
+ generate: ssr ? 'server' : 'client'
68
64
  };
69
65
 
70
- if (options.hot && options.emitCss) {
66
+ if (compileOptions.hmr && options.emitCss) {
71
67
  const hash = `s-${safeBase64Hash(normalizedFilename)}`;
72
68
  compileOptions.cssHash = () => hash;
73
69
  }
74
70
 
75
71
  let preprocessed;
76
72
  let preprocessors = options.preprocess;
77
- if (!options.isBuild && options.emitCss && options.hot) {
73
+ if (!options.isBuild && options.emitCss && compileOptions.hmr) {
78
74
  // inject preprocessor that ensures css hmr works better
79
75
  if (!Array.isArray(preprocessors)) {
80
76
  preprocessors = preprocessors
@@ -132,12 +128,22 @@ export const _createCompileSvelte = (makeHot) => {
132
128
  ...dynamicCompileOptions
133
129
  }
134
130
  : compileOptions;
135
-
136
131
  const endStat = stats?.start(filename);
137
- /** @type {import('svelte/types/compiler/interfaces').CompileResult} */
132
+ /** @type {import('svelte/compiler').CompileResult} */
138
133
  let compiled;
139
134
  try {
140
- compiled = svelte.compile(finalCode, finalCompileOptions);
135
+ compiled = svelte.compile(finalCode, { ...finalCompileOptions, filename: filename });
136
+ // patch output with partial accept until svelte does it
137
+ // TODO remove later
138
+ if (
139
+ options.server?.config.experimental.hmrPartialAccept &&
140
+ compiled.js.code.includes('import.meta.hot.accept(')
141
+ ) {
142
+ compiled.js.code = compiled.js.code.replaceAll(
143
+ 'import.meta.hot.accept(',
144
+ 'import.meta.hot.acceptExports(["default"],'
145
+ );
146
+ }
141
147
  } catch (e) {
142
148
  enhanceCompileError(e, code, preprocessors);
143
149
  throw e;
@@ -156,25 +162,12 @@ export const _createCompileSvelte = (makeHot) => {
156
162
  }
157
163
  if (!raw) {
158
164
  // wire css import and code for hmr
159
- const hasCss = compiled.css?.code?.trim().length > 0;
165
+ const hasCss = compiled.css?.code?.trim()?.length ?? 0 > 0;
160
166
  // compiler might not emit css with mode none or it may be empty
161
167
  if (emitCss && hasCss) {
162
168
  // TODO properly update sourcemap?
163
169
  compiled.js.code += `\nimport ${JSON.stringify(cssId)};\n`;
164
170
  }
165
-
166
- // only apply hmr when not in ssr context and hot options are set
167
- if (!ssr && makeHot) {
168
- compiled.js.code = makeHot({
169
- id: filename,
170
- compiledCode: compiled.js.code,
171
- //@ts-expect-error hot isn't a boolean at this point
172
- hotOptions: { ...options.hot, injectCss: options.hot?.injectCss === true && hasCss },
173
- compiled,
174
- originalCode: code,
175
- compileOptions: finalCompileOptions
176
- });
177
- }
178
171
  }
179
172
 
180
173
  let lang = 'js';
@@ -196,34 +189,4 @@ export const _createCompileSvelte = (makeHot) => {
196
189
  preprocessed: preprocessed ?? { code }
197
190
  };
198
191
  };
199
- };
200
-
201
- /**
202
- * @param {import('../types/options.d.ts').ResolvedOptions} options
203
- * @returns {Function | undefined}
204
- */
205
- function buildMakeHot(options) {
206
- const needsMakeHot =
207
- !isSvelte5 && options.hot !== false && options.isServe && !options.isProduction;
208
- if (needsMakeHot) {
209
- // @ts-ignore
210
- const hotApi = options?.hot?.hotApi;
211
- // @ts-ignore
212
- const adapter = options?.hot?.adapter;
213
- return createMakeHot({
214
- walk: svelte.walk,
215
- hotApi,
216
- adapter,
217
- hotOptions: { noOverlay: true, .../** @type {object} */ (options.hot) }
218
- });
219
- }
220
- }
221
-
222
- /**
223
- * @param {import('../types/options.d.ts').ResolvedOptions} options
224
- * @returns {import('../types/compile.d.ts').CompileSvelte}
225
- */
226
- export function createCompileSvelte(options) {
227
- const makeHot = buildMakeHot(options);
228
- return _createCompileSvelte(makeHot);
229
192
  }
@@ -1,5 +1,3 @@
1
- import { isSvelte5 } from './svelte-version.js';
2
-
3
1
  export const VITE_RESOLVE_MAIN_FIELDS = ['browser', 'module', 'jsnext:main', 'jsnext'];
4
2
 
5
3
  export const SVELTE_RESOLVE_MAIN_FIELDS = ['svelte'];
@@ -10,24 +8,19 @@ export const SVELTE_IMPORTS = [
10
8
  'svelte/internal',
11
9
  'svelte/internal/disclose-version',
12
10
  'svelte/motion',
13
- 'svelte/ssr',
14
11
  'svelte/store',
15
12
  'svelte/transition',
13
+ 'svelte/server',
14
+ 'svelte/internal/server',
15
+ 'svelte/legacy',
16
16
  'svelte'
17
17
  ];
18
18
 
19
- export const SVELTE_HMR_IMPORTS = [
20
- 'svelte-hmr/runtime/hot-api-esm.js',
21
- 'svelte-hmr/runtime/proxy-adapter-dom.js',
22
- 'svelte-hmr'
23
- ];
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
-
30
19
  export const SVELTE_EXPORT_CONDITIONS = ['svelte'];
31
20
 
32
21
  export const FAQ_LINK_MISSING_EXPORTS_CONDITION =
33
22
  'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition';
23
+
24
+ export const DEFAULT_SVELTE_EXT = ['.svelte'];
25
+ export const DEFAULT_SVELTE_MODULE_INFIX = ['.svelte.'];
26
+ export const DEFAULT_SVELTE_MODULE_EXT = ['.js', '.ts'];
@@ -46,7 +46,6 @@ const COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD = [
46
46
  'svelte',
47
47
  'svelte2tsx',
48
48
  'svelte-check',
49
- 'svelte-hmr',
50
49
  'svelte-preprocess',
51
50
  'tslib',
52
51
  'typescript',
@@ -2,7 +2,7 @@ import { buildExtendedLogMessage } from './log.js';
2
2
 
3
3
  /**
4
4
  * convert an error thrown by svelte.compile to a RollupError so that vite displays it in a user friendly way
5
- * @param {import('svelte/types/compiler/interfaces').Warning & Error} error a svelte compiler error, which is a mix of Warning and an error
5
+ * @param {import('svelte/compiler').Warning & Error & {frame?: string}} error a svelte compiler error, which is a mix of Warning and an error
6
6
  * @param {import('../types/options.d.ts').ResolvedOptions} options
7
7
  * @returns {import('vite').Rollup.RollupError} the converted error
8
8
  */
@@ -29,7 +29,7 @@ export function toRollupError(error, options) {
29
29
 
30
30
  /**
31
31
  * convert an error thrown by svelte.compile to an esbuild PartialMessage
32
- * @param {import('svelte/types/compiler/interfaces').Warning & Error} error a svelte compiler error, which is a mix of Warning and an error
32
+ * @param {import('svelte/compiler').Warning & Error & {frame?: string}} error a svelte compiler error, which is a mix of Warning and an error
33
33
  * @param {import('../types/options.d.ts').ResolvedOptions} options
34
34
  * @returns {import('esbuild').PartialMessage} the converted error
35
35
  */
@@ -102,7 +102,7 @@ function formatFrameForVite(frame) {
102
102
  }
103
103
 
104
104
  /**
105
- * @param {import('svelte/types/compiler/interfaces').Warning & Error} err a svelte compiler error, which is a mix of Warning and an error
105
+ * @param {import('svelte/compiler').Warning & Error} err a svelte compiler error, which is a mix of Warning and an error
106
106
  * @param {string} originalCode
107
107
  * @param {import('../public.d.ts').Options['preprocess']} [preprocessors]
108
108
  */
@@ -112,35 +112,6 @@ export function enhanceCompileError(err, originalCode, preprocessors) {
112
112
  /** @type {string[]} */
113
113
  const additionalMessages = [];
114
114
 
115
- // Handle incorrect TypeScript usage
116
- if (err.code === 'parse-error') {
117
- // Reference from Svelte: https://github.com/sveltejs/svelte/blob/9926347ad9dbdd0f3324d5538e25dcb7f5e442f8/packages/svelte/src/compiler/preprocess/index.js#L259
118
- const scriptRe =
119
- /<!--[^]*?-->|<script((?:\s+[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/]+)*\s*)(?:\/>|>([\S\s]*?)<\/script>)/g;
120
- const errIndex = err.pos ?? -1;
121
-
122
- let m;
123
- while ((m = scriptRe.exec(originalCode))) {
124
- const matchStart = m.index;
125
- const matchEnd = matchStart + m[0].length;
126
- const isErrorInScript = matchStart <= errIndex && errIndex <= matchEnd;
127
- if (isErrorInScript) {
128
- // Warn missing lang="ts"
129
- const hasLangTs = m[1]?.includes('lang="ts"');
130
- if (!hasLangTs) {
131
- additionalMessages.push('Did you forget to add lang="ts" to your script tag?');
132
- }
133
- // Warn missing script preprocessor
134
- if (preprocessors.every((p) => p.script == null)) {
135
- const preprocessorType = hasLangTs ? 'TypeScript' : 'script';
136
- additionalMessages.push(
137
- `Did you forget to add a ${preprocessorType} preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
138
- );
139
- }
140
- }
141
- }
142
- }
143
-
144
115
  // Handle incorrect CSS preprocessor usage
145
116
  if (err.code === 'css-syntax-error') {
146
117
  // Reference from Svelte: https://github.com/sveltejs/svelte/blob/9926347ad9dbdd0f3324d5538e25dcb7f5e442f8/packages/svelte/src/compiler/preprocess/index.js#L257
@@ -2,7 +2,6 @@ import { readFileSync } from 'node:fs';
2
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';
6
5
 
7
6
  /**
8
7
  * @typedef {NonNullable<import('vite').DepOptimizationOptions['esbuildOptions']>} EsbuildOptions
@@ -10,8 +9,7 @@ import { isSvelte5 } from './svelte-version.js';
10
9
  */
11
10
 
12
11
  export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade';
13
-
14
- const svelteModuleExtension = '.svelte.js';
12
+ export const facadeEsbuildSvelteModulePluginName = 'vite-plugin-svelte-module:facade';
15
13
 
16
14
  /**
17
15
  * @param {import('../types/options.d.ts').ResolvedOptions} options
@@ -25,19 +23,15 @@ export function esbuildSveltePlugin(options) {
25
23
  // Otherwise this would heavily slow down the scanning phase.
26
24
  if (build.initialOptions.plugins?.some((v) => v.name === 'vite:dep-scan')) return;
27
25
 
28
- const svelteExtensions = (options.extensions ?? ['.svelte']).map((ext) => ext.slice(1));
29
- if (isSvelte5) {
30
- svelteExtensions.push(svelteModuleExtension.slice(1));
31
- }
32
- const svelteFilter = new RegExp('\\.(' + svelteExtensions.join('|') + ')(\\?.*)?$');
26
+ const filter = /\.svelte(?:\?.*)?$/;
33
27
  /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
34
28
  let statsCollection;
35
29
  build.onStart(() => {
36
- statsCollection = options.stats?.startCollection('prebundle libraries', {
30
+ statsCollection = options.stats?.startCollection('prebundle library components', {
37
31
  logResult: (c) => c.stats.length > 1
38
32
  });
39
33
  });
40
- build.onLoad({ filter: svelteFilter }, async ({ path: filename }) => {
34
+ build.onLoad({ filter }, async ({ path: filename }) => {
41
35
  const code = readFileSync(filename, 'utf8');
42
36
  try {
43
37
  const contents = await compileSvelte(options, { filename, code }, statsCollection);
@@ -60,32 +54,18 @@ export function esbuildSveltePlugin(options) {
60
54
  * @returns {Promise<string>}
61
55
  */
62
56
  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
- }
77
57
  let css = options.compilerOptions.css;
78
- if (css !== 'none') {
58
+ if (css !== 'injected') {
79
59
  // TODO ideally we'd be able to externalize prebundled styles too, but for now always put them in the js
80
60
  css = 'injected';
81
61
  }
82
62
  /** @type {import('svelte/compiler').CompileOptions} */
83
63
  const compileOptions = {
64
+ dev: true, // default to dev: true because prebundling is only used in dev
84
65
  ...options.compilerOptions,
85
66
  css,
86
67
  filename,
87
- // @ts-expect-error svelte4 uses 'dom', svelte5 uses 'client'
88
- generate: isSvelte5 ? 'client' : 'dom'
68
+ generate: 'client'
89
69
  };
90
70
 
91
71
  let preprocessed;
@@ -131,3 +111,60 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
131
111
  ? compiled.js.code + '//# sourceMappingURL=' + compiled.js.map.toUrl()
132
112
  : compiled.js.code;
133
113
  }
114
+
115
+ /**
116
+ * @param {import('../types/options.d.ts').ResolvedOptions} options
117
+ * @returns {EsbuildPlugin}
118
+ */
119
+ export function esbuildSvelteModulePlugin(options) {
120
+ return {
121
+ name: 'vite-plugin-svelte-module:optimize-svelte',
122
+ setup(build) {
123
+ // Skip in scanning phase as Vite already handles scanning Svelte files.
124
+ // Otherwise this would heavily slow down the scanning phase.
125
+ if (build.initialOptions.plugins?.some((v) => v.name === 'vite:dep-scan')) return;
126
+
127
+ const filter = /\.svelte\.[jt]s(?:\?.*)?$/;
128
+ /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
129
+ let statsCollection;
130
+ build.onStart(() => {
131
+ statsCollection = options.stats?.startCollection('prebundle library modules', {
132
+ logResult: (c) => c.stats.length > 1
133
+ });
134
+ });
135
+ build.onLoad({ filter }, async ({ path: filename }) => {
136
+ const code = readFileSync(filename, 'utf8');
137
+ try {
138
+ const contents = await compileSvelteModule(options, { filename, code }, statsCollection);
139
+ return { contents };
140
+ } catch (e) {
141
+ return { errors: [toESBuildError(e, options)] };
142
+ }
143
+ });
144
+ build.onEnd(() => {
145
+ statsCollection?.finish();
146
+ });
147
+ }
148
+ };
149
+ }
150
+
151
+ /**
152
+ * @param {import('../types/options.d.ts').ResolvedOptions} options
153
+ * @param {{ filename: string; code: string }} input
154
+ * @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} [statsCollection]
155
+ * @returns {Promise<string>}
156
+ */
157
+ async function compileSvelteModule(options, { filename, code }, statsCollection) {
158
+ const endStat = statsCollection?.start(filename);
159
+ const compiled = svelte.compileModule(code, {
160
+ dev: options.compilerOptions?.dev ?? true, // default to dev: true because prebundling is only used in dev
161
+ filename,
162
+ generate: 'client'
163
+ });
164
+ if (endStat) {
165
+ endStat();
166
+ }
167
+ return compiled.js.map
168
+ ? compiled.js.code + '//# sourceMappingURL=' + compiled.js.map.toUrl()
169
+ : compiled.js.code;
170
+ }
package/src/utils/id.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createFilter, normalizePath } from 'vite';
2
2
  import * as fs from 'node:fs';
3
3
  import { log } from './log.js';
4
+ import { DEFAULT_SVELTE_MODULE_EXT, DEFAULT_SVELTE_MODULE_INFIX } from './constants.js';
4
5
 
5
6
  const VITE_FS_PREFIX = '/@fs/';
6
7
  const IS_WINDOWS = process.platform === 'win32';
@@ -169,6 +170,21 @@ function buildFilter(include, exclude, extensions) {
169
170
  return (filename) => rollupFilter(filename) && extensions.some((ext) => filename.endsWith(ext));
170
171
  }
171
172
 
173
+ /**
174
+ * @param {import('../public.d.ts').Options['include'] | undefined} include
175
+ * @param {import('../public.d.ts').Options['exclude'] | undefined} exclude
176
+ * @param {string[]} infixes
177
+ * @param {string[]} extensions
178
+ * @returns {(filename: string) => boolean}
179
+ */
180
+ function buildModuleFilter(include, exclude, infixes, extensions) {
181
+ const rollupFilter = createFilter(include, exclude);
182
+ return (filename) =>
183
+ rollupFilter(filename) &&
184
+ infixes.some((infix) => filename.includes(infix)) &&
185
+ extensions.some((ext) => filename.endsWith(ext));
186
+ }
187
+
172
188
  /**
173
189
  * @param {import('../types/options.d.ts').ResolvedOptions} options
174
190
  * @returns {import('../types/id.d.ts').IdParser}
@@ -190,10 +206,15 @@ export function buildIdParser(options) {
190
206
  * @returns {import('../types/id.d.ts').ModuleIdParser}
191
207
  */
192
208
  export function buildModuleIdParser(options) {
193
- const { include, exclude, extensions } = options?.experimental?.compileModule ?? {};
209
+ const {
210
+ include,
211
+ exclude,
212
+ infixes = DEFAULT_SVELTE_MODULE_INFIX,
213
+ extensions = DEFAULT_SVELTE_MODULE_EXT
214
+ } = options?.experimental?.compileModule ?? {};
194
215
  const root = options.root;
195
216
  const normalizedRoot = normalizePath(root);
196
- const filter = buildFilter(include, exclude, extensions ?? ['.svelte.js', '.svelte.ts']);
217
+ const filter = buildModuleFilter(include, exclude, infixes, extensions);
197
218
  return (id, ssr, timestamp = Date.now()) => {
198
219
  const { filename, rawQuery } = splitId(id);
199
220
  if (filter(filename)) {
@@ -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
- import { isSvelte4, isSvelte5 } from './svelte-version.js';
4
+
5
5
  /**
6
6
  * utility function to compile ?raw and ?direct requests in load hook
7
7
  *
@@ -18,26 +18,16 @@ 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
- //@ts-ignore //@ts-expect-error generate value differs between svelte4 and 5
22
- svelteRequest.ssr = query.compilerOptions?.generate === (isSvelte4 ? 'ssr' : 'server');
23
- const type = query.type;
21
+ svelteRequest.ssr = query.compilerOptions?.generate === 'server';
24
22
  compileData = await compileSvelte(svelteRequest, source, {
25
23
  ...options,
26
24
  // don't use dynamic vite-plugin-svelte defaults here to ensure stable result between ssr,dev and build
27
25
  compilerOptions: {
28
26
  dev: false,
29
27
  css: 'external',
30
- enableSourcemap: isSvelte5
31
- ? undefined
32
- : query.sourcemap
33
- ? {
34
- js: type === 'script' || type === 'all',
35
- css: type === 'style' || type === 'all'
36
- }
37
- : false,
28
+ hmr: false,
38
29
  ...svelteRequest.query.compilerOptions
39
30
  },
40
- hot: false,
41
31
  emitCss: true
42
32
  });
43
33
  } catch (e) {
@@ -45,7 +35,7 @@ export async function loadRaw(svelteRequest, compileSvelte, options) {
45
35
  }
46
36
  let result;
47
37
  if (query.type === 'style') {
48
- result = compileData.compiled.css;
38
+ result = compileData.compiled.css ?? { code: '', map: null };
49
39
  } else if (query.type === 'script') {
50
40
  result = compileData.compiled.js;
51
41
  } else if (query.type === 'preprocessed') {
@@ -68,7 +58,9 @@ export async function loadRaw(svelteRequest, compileSvelte, options) {
68
58
  }
69
59
  log.debug(`load returns direct result for ${id}`, undefined, 'load');
70
60
  let directOutput = result.code;
61
+ // @ts-expect-error might not be SourceMap but toUrl check should suffice
71
62
  if (query.sourcemap && result.map?.toUrl) {
63
+ // @ts-expect-error
72
64
  const map = `sourceMappingURL=${result.map.toUrl()}`;
73
65
  if (query.type === 'style') {
74
66
  directOutput += `\n\n/*# ${map} */\n`;
package/src/utils/log.js CHANGED
@@ -1,7 +1,6 @@
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';
5
4
 
6
5
  /** @type {import('../types/log.d.ts').LogLevel[]} */
7
6
  const levels = ['debug', 'info', 'warn', 'error', 'silent'];
@@ -128,21 +127,21 @@ export const log = {
128
127
 
129
128
  /**
130
129
  * @param {import('../types/id.d.ts').SvelteRequest | import('../types/id.d.ts').SvelteModuleRequest} svelteRequest
131
- * @param {import('svelte/types/compiler/interfaces').Warning[]} warnings
130
+ * @param {import('svelte/compiler').Warning[]} warnings
132
131
  * @param {import('../types/options.d.ts').ResolvedOptions} options
133
132
  */
134
133
  export function logCompilerWarnings(svelteRequest, warnings, options) {
135
134
  const { emitCss, onwarn, isBuild } = options;
136
135
  const sendViaWS = !isBuild && options.experimental?.sendWarningsToBrowser;
137
136
  let warn = isBuild ? warnBuild : warnDev;
138
- /** @type {import('svelte/types/compiler/interfaces').Warning[]} */
137
+ /** @type {import('svelte/compiler').Warning[]} */
139
138
  const handledByDefaultWarn = [];
140
139
  const notIgnored = warnings?.filter((w) => !ignoreCompilerWarning(w, isBuild, emitCss));
141
140
  const extra = buildExtraWarnings(warnings, isBuild);
142
141
  const allWarnings = [...notIgnored, ...extra];
143
142
  if (sendViaWS) {
144
143
  const _warn = warn;
145
- /** @type {(w: import('svelte/types/compiler/interfaces').Warning) => void} */
144
+ /** @type {(w: import('svelte/compiler').Warning) => void} */
146
145
  warn = (w) => {
147
146
  handledByDefaultWarn.push(w);
148
147
  _warn(w);
@@ -172,7 +171,7 @@ export function logCompilerWarnings(svelteRequest, warnings, options) {
172
171
  }
173
172
 
174
173
  /**
175
- * @param {import('svelte/types/compiler/interfaces').Warning} warning
174
+ * @param {import('svelte/compiler').Warning} warning
176
175
  * @param {boolean} isBuild
177
176
  * @param {boolean} [emitCss]
178
177
  * @returns {boolean}
@@ -186,7 +185,7 @@ function ignoreCompilerWarning(warning, isBuild, emitCss) {
186
185
 
187
186
  /**
188
187
  *
189
- * @param {import('svelte/types/compiler/interfaces').Warning} warning
188
+ * @param {import('svelte/compiler').Warning} warning
190
189
  * @returns {boolean}
191
190
  */
192
191
  function isNoScopableElementWarning(warning) {
@@ -196,9 +195,9 @@ function isNoScopableElementWarning(warning) {
196
195
 
197
196
  /**
198
197
  *
199
- * @param {import('svelte/types/compiler/interfaces').Warning[]} warnings
198
+ * @param {import('svelte/compiler').Warning[]} warnings
200
199
  * @param {boolean} isBuild
201
- * @returns {import('svelte/types/compiler/interfaces').Warning[]}
200
+ * @returns {import('svelte/compiler').Warning[]}
202
201
  */
203
202
  function buildExtraWarnings(warnings, isBuild) {
204
203
  const extraWarnings = [];
@@ -220,21 +219,21 @@ function buildExtraWarnings(warnings, isBuild) {
220
219
  }
221
220
 
222
221
  /**
223
- * @param {import('svelte/types/compiler/interfaces').Warning} w
222
+ * @param {import('svelte/compiler').Warning} w
224
223
  */
225
224
  function warnDev(w) {
226
225
  log.info.enabled && log.info(buildExtendedLogMessage(w));
227
226
  }
228
227
 
229
228
  /**
230
- * @param {import('svelte/types/compiler/interfaces').Warning} w
229
+ * @param {import('svelte/compiler').Warning & {frame?: string}} w
231
230
  */
232
231
  function warnBuild(w) {
233
232
  log.warn.enabled && log.warn(buildExtendedLogMessage(w), w.frame);
234
233
  }
235
234
 
236
235
  /**
237
- * @param {import('svelte/types/compiler/interfaces').Warning} w
236
+ * @param {import('svelte/compiler').Warning} w
238
237
  */
239
238
  export function buildExtendedLogMessage(w) {
240
239
  const parts = [];
@@ -260,9 +259,3 @@ export function buildExtendedLogMessage(w) {
260
259
  export function isDebugNamespaceEnabled(namespace) {
261
260
  return debug.enabled(`${prefix}:${namespace}`);
262
261
  }
263
-
264
- export function logSvelte5Warning() {
265
- const notice = `You are using Svelte ${VERSION}. Svelte 5 support is experimental, breaking changes can occur in any release until this notice is removed.`;
266
- const wip = ['svelte-inspector is disabled until dev mode implements node to code mapping'];
267
- log.warn(`${notice}\nwork in progress:\n - ${wip.join('\n - ')}\n`);
268
- }
@@ -3,16 +3,21 @@ import { normalizePath } from 'vite';
3
3
  import { isDebugNamespaceEnabled, log } from './log.js';
4
4
  import { loadSvelteConfig } from './load-svelte-config.js';
5
5
  import {
6
+ DEFAULT_SVELTE_EXT,
6
7
  FAQ_LINK_MISSING_EXPORTS_CONDITION,
7
8
  SVELTE_EXPORT_CONDITIONS,
8
- SVELTE_HMR_IMPORTS,
9
9
  SVELTE_IMPORTS,
10
10
  SVELTE_RESOLVE_MAIN_FIELDS,
11
11
  VITE_RESOLVE_MAIN_FIELDS
12
12
  } from './constants.js';
13
13
 
14
14
  import path from 'node:path';
15
- import { esbuildSveltePlugin, facadeEsbuildSveltePluginName } from './esbuild.js';
15
+ import {
16
+ esbuildSvelteModulePlugin,
17
+ esbuildSveltePlugin,
18
+ facadeEsbuildSvelteModulePluginName,
19
+ facadeEsbuildSveltePluginName
20
+ } from './esbuild.js';
16
21
  import { addExtraPreprocessors } from './preprocess.js';
17
22
  import deepmerge from 'deepmerge';
18
23
  import {
@@ -26,7 +31,6 @@ import {
26
31
  import { isCommonDepWithoutSvelteField } from './dependencies.js';
27
32
  import { VitePluginSvelteStats } from './vite-plugin-svelte-stats.js';
28
33
  import { VitePluginSvelteCache } from './vite-plugin-svelte-cache.js';
29
- import { isSvelte5, isSvelte5WithHMRSupport } from './svelte-version.js';
30
34
 
31
35
  const allowedPluginOptions = new Set([
32
36
  'include',
@@ -139,7 +143,7 @@ export async function preResolveOptions(inlineOptions, viteUserConfig, viteEnv)
139
143
  const isBuild = viteEnv.command === 'build';
140
144
  /** @type {Partial<import('../types/options.d.ts').PreResolvedOptions>} */
141
145
  const defaultOptions = {
142
- extensions: ['.svelte'],
146
+ extensions: DEFAULT_SVELTE_EXT,
143
147
  emitCss: true,
144
148
  prebundleSvelteLibraries: !isBuild
145
149
  };
@@ -196,22 +200,11 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
196
200
  const defaultOptions = {
197
201
  compilerOptions: {
198
202
  css,
199
- dev: !viteConfig.isProduction
203
+ dev: !viteConfig.isProduction,
204
+ hmr: !viteConfig.isProduction && !preResolveOptions.isBuild
200
205
  }
201
206
  };
202
- if (isSvelte5) {
203
- if (isSvelte5WithHMRSupport) {
204
- // @ts-expect-error svelte4 does not have hmr option
205
- defaultOptions.compilerOptions.hmr = !viteConfig.isProduction;
206
- }
207
- } else {
208
- defaultOptions.hot = viteConfig.isProduction
209
- ? false
210
- : {
211
- injectCss: css === 'injected',
212
- partialAccept: !!viteConfig.experimental?.hmrPartialAccept
213
- };
214
- }
207
+
215
208
  /** @type {Partial<import('../types/options.d.ts').ResolvedOptions>} */
216
209
  const extraOptions = {
217
210
  root: viteConfig.root,
@@ -237,55 +230,12 @@ export function resolveOptions(preResolveOptions, viteConfig, cache) {
237
230
  * @param {import('../types/options.d.ts').ResolvedOptions} options
238
231
  */
239
232
  function enforceOptionsForHmr(options) {
240
- if (isSvelte5) {
241
- if (options.hot && isSvelte5WithHMRSupport) {
242
- log.warn(
243
- 'svelte 5 has hmr integrated in core. Please remove the hot option and use compilerOptions.hmr instead'
244
- );
245
- delete options.hot;
246
- // @ts-expect-error hmr option doesn't exist in svelte4
247
- options.compilerOptions.hmr = true;
248
- }
249
- } else {
250
- if (options.hot) {
251
- if (!options.compilerOptions.dev) {
252
- log.warn('hmr is enabled but compilerOptions.dev is false, forcing it to true');
253
- options.compilerOptions.dev = true;
254
- }
255
- if (options.emitCss) {
256
- if (options.hot !== true && options.hot.injectCss) {
257
- log.warn('hmr and emitCss are enabled but hot.injectCss is true, forcing it to false');
258
- options.hot.injectCss = false;
259
- }
260
- const css = options.compilerOptions.css;
261
- if (css === true || css === 'injected') {
262
- const forcedCss = 'external';
263
- log.warn(
264
- `hmr and emitCss are enabled but compilerOptions.css is ${css}, forcing it to ${forcedCss}`
265
- );
266
- options.compilerOptions.css = forcedCss;
267
- }
268
- } else {
269
- if (options.hot === true || !options.hot.injectCss) {
270
- log.warn(
271
- 'hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true'
272
- );
273
- if (options.hot === true) {
274
- options.hot = { injectCss: true };
275
- } else {
276
- options.hot.injectCss = true;
277
- }
278
- }
279
- const css = options.compilerOptions.css;
280
- if (!(css === true || css === 'injected')) {
281
- const forcedCss = 'injected';
282
- log.warn(
283
- `hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to ${forcedCss}`
284
- );
285
- options.compilerOptions.css = forcedCss;
286
- }
287
- }
288
- }
233
+ if (options.hot) {
234
+ log.warn(
235
+ 'svelte 5 has hmr integrated in core. Please remove the vitePlugin.hot option and use compilerOptions.hmr instead'
236
+ );
237
+ delete options.hot;
238
+ options.compilerOptions.hmr = true;
289
239
  }
290
240
  }
291
241
 
@@ -294,9 +244,11 @@ function enforceOptionsForHmr(options) {
294
244
  */
295
245
  function enforceOptionsForProduction(options) {
296
246
  if (options.isProduction) {
297
- if (options.hot) {
298
- log.warn('options.hot is enabled but does not work on production build, forcing it to false');
299
- options.hot = false;
247
+ if (options.compilerOptions.hmr) {
248
+ log.warn(
249
+ 'you are building for production but compilerOptions.hmr is true, forcing it to false'
250
+ );
251
+ options.compilerOptions.hmr = false;
300
252
  }
301
253
  if (options.compilerOptions.dev) {
302
254
  log.warn(
@@ -384,7 +336,7 @@ export async function buildExtraViteConfig(options, config) {
384
336
  /** @type {Partial<import('vite').UserConfig>} */
385
337
  const extraViteConfig = {
386
338
  resolve: {
387
- dedupe: [...SVELTE_IMPORTS, ...SVELTE_HMR_IMPORTS],
339
+ dedupe: [...SVELTE_IMPORTS],
388
340
  conditions: [...SVELTE_EXPORT_CONDITIONS]
389
341
  }
390
342
  // this option is still awaiting a PR in vite to be supported
@@ -437,18 +389,16 @@ export async function buildExtraViteConfig(options, config) {
437
389
  // Currently a placeholder as more information is needed after Vite config is resolved,
438
390
  // the real Svelte plugin is added in `patchResolvedViteConfig()`
439
391
  esbuildOptions: {
440
- plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
392
+ plugins: [
393
+ { name: facadeEsbuildSveltePluginName, setup: () => {} },
394
+ { name: facadeEsbuildSvelteModulePluginName, setup: () => {} }
395
+ ]
441
396
  }
442
397
  };
443
398
  }
444
399
 
445
400
  // enable hmrPartialAccept if not explicitly disabled
446
- if (
447
- (options.hot == null ||
448
- options.hot === true ||
449
- (options.hot && options.hot.partialAccept !== false)) && // deviate from svelte-hmr, default to true
450
- config.experimental?.hmrPartialAccept !== false
451
- ) {
401
+ if (config.experimental?.hmrPartialAccept !== false) {
452
402
  log.debug('enabling "experimental.hmrPartialAccept" in vite config', undefined, 'config');
453
403
  extraViteConfig.experimental = { hmrPartialAccept: true };
454
404
  }
@@ -593,9 +543,10 @@ function buildExtraConfigForSvelte(config) {
593
543
  // include svelte imports for optimization unless explicitly excluded
594
544
  /** @type {string[]} */
595
545
  const include = [];
596
- const exclude = ['svelte-hmr'];
546
+ /** @type {string[]} */
547
+ const exclude = [];
597
548
  if (!isDepExcluded('svelte', config.optimizeDeps?.exclude ?? [])) {
598
- const svelteImportsToInclude = SVELTE_IMPORTS.filter((x) => x !== 'svelte/ssr'); // not used on clientside
549
+ const svelteImportsToInclude = SVELTE_IMPORTS;
599
550
  log.debug(
600
551
  `adding bare svelte packages to optimizeDeps.include: ${svelteImportsToInclude.join(', ')} `,
601
552
  undefined,
@@ -614,7 +565,7 @@ function buildExtraConfigForSvelte(config) {
614
565
  /** @type {string[]} */
615
566
  const external = [];
616
567
  // add svelte to ssr.noExternal unless it is present in ssr.external
617
- // so we can resolve it with svelte/ssr
568
+ // so it is correctly resolving according to the conditions in sveltes exports map
618
569
  if (!isDepExternaled('svelte', config.ssr?.external ?? [])) {
619
570
  noExternal.push('svelte', /^svelte\//);
620
571
  }
@@ -641,6 +592,12 @@ export function patchResolvedViteConfig(viteConfig, options) {
641
592
  if (facadeEsbuildSveltePlugin) {
642
593
  Object.assign(facadeEsbuildSveltePlugin, esbuildSveltePlugin(options));
643
594
  }
595
+ const facadeEsbuildSvelteModulePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find(
596
+ (plugin) => plugin.name === facadeEsbuildSvelteModulePluginName
597
+ );
598
+ if (facadeEsbuildSvelteModulePlugin) {
599
+ Object.assign(facadeEsbuildSvelteModulePlugin, esbuildSvelteModulePlugin(options));
600
+ }
644
601
  }
645
602
 
646
603
  /**
@@ -127,10 +127,10 @@ export function addExtraPreprocessors(options, config) {
127
127
  *
128
128
  * @param filename {string}
129
129
  * @param dependencies {string[]}
130
- * @returns {({dependencies: string[], warnings:import('svelte/types/compiler/interfaces').Warning[] })}
130
+ * @returns {({dependencies: string[], warnings:import('svelte/compiler').Warning[] })}
131
131
  */
132
132
  export function checkPreprocessDependencies(filename, dependencies) {
133
- /** @type {import('svelte/types/compiler/interfaces').Warning[]} */
133
+ /** @type {import('svelte/compiler').Warning[]} */
134
134
  const warnings = [];
135
135
 
136
136
  // to find self, we have to compare normalized filenames, but must keep the original values in `dependencies`
@@ -1,10 +1,5 @@
1
1
  import { VERSION } from 'svelte/compiler';
2
2
 
3
- /**
4
- * @type {boolean}
5
- */
6
- export const isSvelte4 = VERSION.startsWith('4.');
7
-
8
3
  /**
9
4
  * @type {boolean}
10
5
  */
@@ -16,9 +16,9 @@ import { normalizePath } from 'vite';
16
16
  * @class
17
17
  */
18
18
  export class VitePluginSvelteCache {
19
- /** @type {Map<string, import('../types/compile.d.ts').Code>} */
19
+ /** @type {Map<string, import('../types/compile.d.ts').Code | null>} */
20
20
  #css = new Map();
21
- /** @type {Map<string, import('../types/compile.d.ts').Code>} */
21
+ /** @type {Map<string, import('../types/compile.d.ts').Code | null>} */
22
22
  #js = new Map();
23
23
  /** @type {Map<string, string[]>} */
24
24
  #dependencies = new Map();
@@ -133,7 +133,7 @@ export class VitePluginSvelteCache {
133
133
 
134
134
  /**
135
135
  * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
136
- * @returns {import('../types/compile.d.ts').Code | undefined}
136
+ * @returns {import('../types/compile.d.ts').Code | undefined | null}
137
137
  */
138
138
  getCSS(svelteRequest) {
139
139
  return this.#css.get(svelteRequest.normalizedFilename);
@@ -141,7 +141,7 @@ export class VitePluginSvelteCache {
141
141
 
142
142
  /**
143
143
  * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
144
- * @returns {import('../types/compile.d.ts').Code | undefined}
144
+ * @returns {import('../types/compile.d.ts').Code | undefined | null}
145
145
  */
146
146
  getJS(svelteRequest) {
147
147
  if (!svelteRequest.ssr) {
package/types/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  declare module '@sveltejs/vite-plugin-svelte' {
2
2
  import type { InlineConfig, ResolvedConfig } from 'vite';
3
- import type { CompileOptions, PreprocessorGroup } from 'svelte/compiler';
4
- import type { Warning } from 'svelte/types/compiler/interfaces';
3
+ import type { CompileOptions, Warning, PreprocessorGroup } from 'svelte/compiler';
5
4
  import type { Options as InspectorOptions } from '@sveltejs/vite-plugin-svelte-inspector';
6
5
  export type Options = Omit<SvelteConfig, 'vitePlugin'> & PluginOptionsInline;
7
6
 
@@ -39,27 +38,13 @@ declare module '@sveltejs/vite-plugin-svelte' {
39
38
  emitCss?: boolean;
40
39
  /**
41
40
  * Enable or disable Hot Module Replacement.
41
+ * Deprecated, use compilerOptions.hmr instead!
42
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
43
+ * @deprecated
54
44
  * @default true for development, always false for production
55
45
  */
56
- hot?:
57
- | boolean
58
- | {
59
- injectCss?: boolean;
60
- partialAccept?: boolean;
61
- [key: string]: any;
62
- };
46
+ hot?: boolean;
47
+
63
48
  /**
64
49
  * Some Vite plugins can contribute additional preprocessors by defining `api.sveltePreprocess`.
65
50
  * If you don't want to use them, set this to true to ignore them all or use an array of strings
@@ -150,8 +135,18 @@ declare module '@sveltejs/vite-plugin-svelte' {
150
135
 
151
136
  /**
152
137
  * Handles warning emitted from the Svelte compiler
138
+ *
139
+ * @example
140
+ * ```
141
+ * (warning, defaultHandler) => {
142
+ * // ignore some warnings
143
+ * if (!['foo','bar'].includes(warning.code)) {
144
+ * defaultHandler(warning);
145
+ * }
146
+ * }
147
+ * ```
153
148
  */
154
- onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void;
149
+ onwarn?: (warning: Warning, defaultHandler: (warning: Warning) => void) => void;
155
150
  /**
156
151
  * Options for vite-plugin-svelte
157
152
  */
@@ -178,6 +173,15 @@ declare module '@sveltejs/vite-plugin-svelte' {
178
173
  }
179
174
 
180
175
  interface CompileModuleOptions {
176
+ /**
177
+ * infix that must be present in filename
178
+ * @default ['.svelte.']
179
+ */
180
+ infixes?: string[];
181
+ /**
182
+ * module extensions
183
+ * @default ['.ts','.js']
184
+ */
181
185
  extensions?: string[];
182
186
  include?: Arrayable<string>;
183
187
  exclude?: Arrayable<string>;
@@ -186,7 +190,16 @@ declare module '@sveltejs/vite-plugin-svelte' {
186
190
  type Arrayable<T> = T | T[];
187
191
 
188
192
  export interface VitePreprocessOptions {
193
+ /**
194
+ * preprocess script block with vite pipeline.
195
+ * Since svelte5 this is not needed for typescript anymore
196
+ *
197
+ * @default false
198
+ */
189
199
  script?: boolean;
200
+ /**
201
+ * preprocess style blocks with vite pipeline
202
+ */
190
203
  style?: boolean | InlineConfig | ResolvedConfig;
191
204
  }
192
205
  export function svelte(inlineOptions?: Partial<Options> | undefined): import('vite').Plugin[];
@@ -21,5 +21,5 @@
21
21
  null,
22
22
  null
23
23
  ],
24
- "mappings": ";;;;;aAMYA,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA2HFC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA2DZC,qBAAqBA;;;;iBChKtBC,MAAMA;iBCbNC,cAAcA;iBCgBRC,gBAAgBA"
24
+ "mappings": ";;;;aAMYA,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6GFC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA8EZC,qBAAqBA;;;;;;;;;;;;;iBCzKtBC,MAAMA;iBCTNC,cAAcA;iBCgBRC,gBAAgBA"
25
25
  }