@sveltejs/vite-plugin-svelte 6.0.0-next.2 → 6.0.0

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": "6.0.0-next.2",
3
+ "version": "6.0.0",
4
4
  "license": "MIT",
5
5
  "author": "dominikg",
6
6
  "files": [
@@ -34,12 +34,12 @@
34
34
  },
35
35
  "homepage": "https://github.com/sveltejs/vite-plugin-svelte#readme",
36
36
  "dependencies": {
37
- "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0-next.0",
37
+ "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0-next.1",
38
38
  "debug": "^4.4.1",
39
39
  "deepmerge": "^4.3.1",
40
40
  "kleur": "^4.1.5",
41
41
  "magic-string": "^0.30.17",
42
- "vitefu": "^1.0.7"
42
+ "vitefu": "^1.1.1"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "svelte": "^5.0.0",
@@ -48,8 +48,8 @@
48
48
  "devDependencies": {
49
49
  "@types/debug": "^4.1.12",
50
50
  "sass": "^1.89.2",
51
- "svelte": "^5.34.9",
52
- "vite": "^7.0.0"
51
+ "svelte": "^5.35.2",
52
+ "vite": "^7.0.2"
53
53
  },
54
54
  "scripts": {
55
55
  "check:publint": "publint --strict",
@@ -1,6 +1,5 @@
1
1
  import { toRollupError } from '../utils/error.js';
2
2
  import { logCompilerWarnings } from '../utils/log.js';
3
- import { ensureWatchedFile } from '../utils/watch.js';
4
3
 
5
4
  /**
6
5
  * @param {import('../types/plugin-api.d.ts').PluginAPI} api
@@ -32,37 +31,30 @@ export function compile(api) {
32
31
  if (!svelteRequest || svelteRequest.raw) {
33
32
  return;
34
33
  }
35
- const cache = api.getEnvironmentCache(this);
36
34
  let compileData;
37
35
  try {
38
- const svelteMeta = this.getModuleInfo(id)?.meta?.svelte;
39
- compileData = await compileSvelte(svelteRequest, code, options, svelteMeta?.preprocessed);
36
+ compileData = await compileSvelte(
37
+ svelteRequest,
38
+ code,
39
+ options,
40
+ this.getCombinedSourcemap()
41
+ );
40
42
  } catch (e) {
41
- cache.setError(svelteRequest, e);
42
43
  throw toRollupError(e, options);
43
44
  }
44
45
  if (compileData.compiled?.warnings) {
45
46
  logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options);
46
47
  }
47
48
 
48
- cache.update(compileData);
49
- if (compileData.dependencies?.length) {
50
- if (options.server) {
51
- for (const dep of compileData.dependencies) {
52
- ensureWatchedFile(options.server.watcher, dep, options.root);
53
- }
54
- } else if (options.isBuild && this.environment.config.build.watch) {
55
- for (const dep of compileData.dependencies) {
56
- this.addWatchFile(dep);
57
- }
58
- }
59
- }
60
49
  return {
61
50
  ...compileData.compiled.js,
62
51
  moduleType: 'js',
63
52
  meta: {
64
53
  vite: {
65
54
  lang: compileData.lang
55
+ },
56
+ svelte: {
57
+ css: compileData.compiled.css
66
58
  }
67
59
  }
68
60
  };
@@ -1,7 +1,6 @@
1
1
  import process from 'node:process';
2
2
  import { isDebugNamespaceEnabled, log } from '../utils/log.js';
3
3
  import * as vite from 'vite';
4
- import { VitePluginSvelteCache } from '../utils/vite-plugin-svelte-cache.js';
5
4
  import { VitePluginSvelteStats } from '../utils/vite-plugin-svelte-stats.js';
6
5
  import {
7
6
  buildExtraViteConfig,
@@ -14,8 +13,8 @@ import {
14
13
  import { buildIdFilter, buildIdParser } from '../utils/id.js';
15
14
  import { createCompileSvelte } from '../utils/compile.js';
16
15
 
17
- // @ts-expect-error rolldownVersion
18
- const { version: viteVersion, rolldownVersion, perEnvironmentState } = vite;
16
+ // @ts-ignore rolldownVersion
17
+ const { version: viteVersion, rolldownVersion } = vite;
19
18
 
20
19
  /**
21
20
  * @param {Partial<import('../public.d.ts').Options>} [inlineOptions]
@@ -71,8 +70,7 @@ export function configure(api, inlineOptions) {
71
70
  if (isDebugNamespaceEnabled('stats')) {
72
71
  api.options.stats = new VitePluginSvelteStats();
73
72
  }
74
- //@ts-expect-error perEnvironmentState uses a wider type for PluginContext
75
- api.getEnvironmentCache = perEnvironmentState((_env) => new VitePluginSvelteCache());
73
+
76
74
  api.idFilter = buildIdFilter(options);
77
75
 
78
76
  api.idParser = buildIdParser(options);
@@ -57,7 +57,7 @@ export function hotUpdate(api) {
57
57
  (e) => e.config.consumer === 'client'
58
58
  );
59
59
  if (clientEnvironment) {
60
- setupWatchers(options, api.getEnvironmentCache({ environment: clientEnvironment }));
60
+ setupWatchers(options);
61
61
  } else {
62
62
  log.warn(
63
63
  'No client environment found, not adding watchers for svelte config and preprocessor dependencies'
@@ -26,16 +26,14 @@ export function loadCompiledCss(api) {
26
26
  if (!svelteRequest) {
27
27
  return;
28
28
  }
29
- const cache = api.getEnvironmentCache(this);
30
- const cachedCss = cache.getCSS(svelteRequest);
29
+ const cachedCss = this.getModuleInfo(svelteRequest.filename)?.meta.svelte?.css;
31
30
  if (cachedCss) {
32
31
  const { hasGlobal, ...css } = cachedCss;
33
32
  if (hasGlobal === false) {
34
33
  // hasGlobal was added in svelte 5.26.0, so make sure it is boolean false
35
34
  css.meta ??= {};
36
35
  css.meta.vite ??= {};
37
- // TODO is that slice the best way to get the filename without parsing the id?
38
- css.meta.vite.cssScopeTo = [id.slice(0, id.lastIndexOf('?')), 'default'];
36
+ css.meta.vite.cssScopeTo = [svelteRequest.filename, 'default'];
39
37
  }
40
38
  css.moduleType = 'css';
41
39
  return css;
@@ -3,6 +3,8 @@ import { mapToRelative } from '../utils/sourcemaps.js';
3
3
  import * as svelte from 'svelte/compiler';
4
4
  import { log } from '../utils/log.js';
5
5
  import { arraify } from '../utils/options.js';
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
6
8
 
7
9
  /**
8
10
  * @param {import('../types/plugin-api.d.ts').PluginAPI} api
@@ -14,10 +16,16 @@ export function preprocess(api) {
14
16
  */
15
17
  let options;
16
18
 
19
+ /**
20
+ * @type {DependenciesCache}
21
+ */
22
+ let dependenciesCache;
23
+
17
24
  /**
18
25
  * @type {import("../types/compile.d.ts").PreprocessSvelte}
19
26
  */
20
27
  let preprocessSvelte;
28
+
21
29
  /** @type {import('vite').Plugin} */
22
30
  const plugin = {
23
31
  name: 'vite-plugin-svelte:preprocess',
@@ -37,19 +45,39 @@ export function preprocess(api) {
37
45
  delete plugin.transform;
38
46
  }
39
47
  },
40
-
48
+ configureServer(server) {
49
+ dependenciesCache = new DependenciesCache(server);
50
+ },
51
+ buildStart() {
52
+ dependenciesCache?.clear();
53
+ },
41
54
  transform: {
42
55
  async handler(code, id) {
43
- const cache = api.getEnvironmentCache(this);
44
56
  const ssr = this.environment.config.consumer === 'server';
45
57
  const svelteRequest = api.idParser(id, ssr);
46
58
  if (!svelteRequest) {
47
59
  return;
48
60
  }
49
61
  try {
50
- return await preprocessSvelte(svelteRequest, code, options);
62
+ const preprocessed = await preprocessSvelte(svelteRequest, code, options);
63
+ dependenciesCache?.update(svelteRequest, preprocessed?.dependencies ?? []);
64
+ if (!preprocessed) {
65
+ return;
66
+ }
67
+ if (options.isBuild && this.environment.config.build.watch && preprocessed.dependencies) {
68
+ for (const dep of preprocessed.dependencies) {
69
+ this.addWatchFile(dep);
70
+ }
71
+ }
72
+
73
+ /** @type {import('vite').Rollup.SourceDescription}*/
74
+ const result = { code: preprocessed.code };
75
+ if (preprocessed.map) {
76
+ // @ts-expect-error type differs but should work
77
+ result.map = preprocessed.map;
78
+ }
79
+ return result;
51
80
  } catch (e) {
52
- cache.setError(svelteRequest, e);
53
81
  throw toRollupError(e, options);
54
82
  }
55
83
  }
@@ -63,8 +91,6 @@ export function preprocess(api) {
63
91
  * @returns {import('../types/compile.d.ts').PreprocessSvelte}
64
92
  */
65
93
  function createPreprocessSvelte(options, resolvedConfig) {
66
- /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
67
- let stats;
68
94
  /** @type {Array<import('svelte/compiler').PreprocessorGroup>} */
69
95
  const preprocessors = arraify(options.preprocess);
70
96
 
@@ -75,59 +101,105 @@ function createPreprocessSvelte(options, resolvedConfig) {
75
101
  }
76
102
 
77
103
  /** @type {import('../types/compile.d.ts').PreprocessSvelte} */
78
- return async function preprocessSvelte(svelteRequest, code, options) {
79
- const { filename, ssr } = svelteRequest;
80
-
81
- if (options.stats) {
82
- if (options.isBuild) {
83
- if (!stats) {
84
- // build is either completely ssr or csr, create stats collector on first compile
85
- // it is then finished in the buildEnd hook.
86
- stats = options.stats.startCollection(`${ssr ? 'ssr' : 'dom'} preprocess`, {
87
- logInProgress: () => false
88
- });
89
- }
90
- } else {
91
- // dev time ssr, it's a ssr request and there are no stats, assume new page load and start collecting
92
- if (ssr && !stats) {
93
- stats = options.stats.startCollection('ssr preprocess');
94
- }
95
- // stats are being collected but this isn't an ssr request, assume page loaded and stop collecting
96
- if (!ssr && stats) {
97
- stats.finish();
98
- stats = undefined;
99
- }
100
- // TODO find a way to trace dom compile during dev
101
- // problem: we need to call finish at some point but have no way to tell if page load finished
102
- // also they for hmr updates too
103
- }
104
- }
105
-
104
+ return async function preprocessSvelte(svelteRequest, code) {
105
+ const { filename } = svelteRequest;
106
106
  let preprocessed;
107
-
108
107
  if (preprocessors && preprocessors.length > 0) {
109
108
  try {
110
- const endStat = stats?.start(filename);
111
109
  preprocessed = await svelte.preprocess(code, preprocessors, { filename }); // full filename here so postcss works
112
- endStat?.();
113
110
  } catch (e) {
114
111
  e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;
115
112
  throw e;
116
113
  }
117
-
118
114
  if (typeof preprocessed?.map === 'object') {
119
115
  mapToRelative(preprocessed?.map, filename);
120
116
  }
121
- return /** @type {import('../types/compile.d.ts').PreprocessTransformOutput} */ {
122
- code: preprocessed.code,
123
- // @ts-expect-error
124
- map: preprocessed.map,
125
- meta: {
126
- svelte: {
127
- preprocessed
128
- }
129
- }
130
- };
117
+ return preprocessed;
131
118
  }
132
119
  };
133
120
  }
121
+
122
+ /**
123
+ * @class
124
+ *
125
+ * caches dependencies of preprocessed files and emit change events on dependants
126
+ */
127
+ class DependenciesCache {
128
+ /** @type {Map<string, string[]>} */
129
+ #dependencies = new Map();
130
+ /** @type {Map<string, Set<string>>} */
131
+ #dependants = new Map();
132
+
133
+ /** @type {import('vite').ViteDevServer} */
134
+ #server;
135
+ /**
136
+ *
137
+ * @param {import('vite').ViteDevServer} server
138
+ */
139
+ constructor(server) {
140
+ this.#server = server;
141
+ /** @type {(filename: string) => void} */
142
+ const emitChangeEventOnDependants = (filename) => {
143
+ const dependants = this.#dependants.get(filename);
144
+ dependants?.forEach((dependant) => {
145
+ if (fs.existsSync(dependant)) {
146
+ log.debug(
147
+ `emitting virtual change event for "${dependant}" because dependency "${filename}" changed`,
148
+ undefined,
149
+ 'hmr'
150
+ );
151
+ server.watcher.emit('change', dependant);
152
+ }
153
+ });
154
+ };
155
+ server.watcher.on('change', emitChangeEventOnDependants);
156
+ server.watcher.on('unlink', emitChangeEventOnDependants);
157
+ }
158
+
159
+ /**
160
+ * @param {string} file
161
+ */
162
+ #ensureWatchedFile(file) {
163
+ const root = this.#server.config.root;
164
+ if (
165
+ file &&
166
+ // only need to watch if out of root
167
+ !file.startsWith(root + '/') &&
168
+ // some rollup plugins use null bytes for private resolved Ids
169
+ !file.includes('\0') &&
170
+ fs.existsSync(file)
171
+ ) {
172
+ // resolve file to normalized system path
173
+ this.#server.watcher.add(path.resolve(file));
174
+ }
175
+ }
176
+
177
+ clear() {
178
+ this.#dependencies.clear();
179
+ this.#dependants.clear();
180
+ }
181
+
182
+ /**
183
+ *
184
+ * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
185
+ * @param {string[]} dependencies
186
+ */
187
+ update(svelteRequest, dependencies) {
188
+ const id = svelteRequest.normalizedFilename;
189
+ const prevDependencies = this.#dependencies.get(id) || [];
190
+
191
+ this.#dependencies.set(id, dependencies);
192
+ const removed = prevDependencies.filter((d) => !dependencies.includes(d));
193
+ const added = dependencies.filter((d) => !prevDependencies.includes(d));
194
+ added.forEach((d) => {
195
+ this.#ensureWatchedFile(d);
196
+ if (!this.#dependants.has(d)) {
197
+ this.#dependants.set(d, new Set());
198
+ }
199
+ /** @type {Set<string>} */ (this.#dependants.get(d)).add(svelteRequest.filename);
200
+ });
201
+ removed.forEach((d) => {
202
+ /** @type {Set<string>} */ (this.#dependants.get(d)).delete(svelteRequest.filename);
203
+ });
204
+ }
205
+ }
@@ -7,7 +7,7 @@ import { toESBuildError, toRollupError } from '../utils/error.js';
7
7
  import { safeBase64Hash } from '../utils/hash.js';
8
8
  import { normalize } from '../utils/id.js';
9
9
  import * as vite from 'vite';
10
- // @ts-expect-error not typed on vite
10
+ // @ts-ignore not typed on vite
11
11
  const { rolldownVersion } = vite;
12
12
 
13
13
  /**
@@ -42,7 +42,7 @@ export function setupOptimizer(api) {
42
42
  // Currently, a placeholder as more information is needed after Vite config is resolved,
43
43
  // the added plugins are patched in configResolved below
44
44
  if (rolldownVersion) {
45
- //@ts-expect-error rolldown types not finished
45
+ //@ts-ignore rolldown types not finished
46
46
  optimizeDeps.rollupOptions = {
47
47
  plugins: [
48
48
  placeholderRolldownOptimizerPlugin(optimizeSveltePluginName),
package/src/preprocess.js CHANGED
@@ -6,9 +6,9 @@ const {
6
6
  preprocessCSS,
7
7
  resolveConfig,
8
8
  transformWithEsbuild,
9
- //@ts-expect-error rolldown types don't exist
9
+ //@ts-ignore rolldown types don't exist
10
10
  rolldownVersion,
11
- //@ts-expect-error rolldown types don't exist
11
+ //@ts-ignore rolldown types don't exist
12
12
  transformWithOxc
13
13
  } = vite;
14
14
  /**
@@ -72,8 +72,10 @@ function viteScript() {
72
72
  function viteScriptOxc() {
73
73
  return {
74
74
  async script({ attributes, content, filename = '' }) {
75
- const lang = /** @type {string} */ (attributes.lang);
76
- if (!supportedScriptLangs.includes(lang)) return;
75
+ if (typeof attributes.lang !== 'string' || !supportedScriptLangs.includes(attributes.lang)) {
76
+ return;
77
+ }
78
+ const lang = /** @type {'ts'} */ (attributes.lang);
77
79
  const { code, map } = await transformWithOxc(content, filename, {
78
80
  lang,
79
81
  target: 'esnext'
package/src/public.d.ts CHANGED
@@ -173,6 +173,13 @@ interface ExperimentalOptions {
173
173
  */
174
174
  disableSvelteResolveWarnings?: boolean;
175
175
 
176
+ /**
177
+ * disable api.sveltePreprocess deprecation warnings
178
+ *
179
+ * @default false
180
+ */
181
+ disableApiSveltePreprocessWarnings?: boolean;
182
+
176
183
  compileModule?: CompileModuleOptions;
177
184
  }
178
185
 
@@ -7,24 +7,14 @@ export type CompileSvelte = (
7
7
  svelteRequest: SvelteRequest,
8
8
  code: string,
9
9
  options: Partial<ResolvedOptions>,
10
- preprocessed?: Processed
10
+ sourcemap?: Rollup.SourceMap
11
11
  ) => Promise<CompileData>;
12
12
 
13
13
  export type PreprocessSvelte = (
14
14
  svelteRequest: SvelteRequest,
15
15
  code: string,
16
16
  options: Partial<ResolvedOptions>
17
- ) => Promise<PreprocessTransformOutput | undefined>;
18
-
19
- export interface PreprocessTransformOutput {
20
- code: string;
21
- map: Rollup.SourceMapInput;
22
- meta: {
23
- svelte: {
24
- preprocessed: Processed;
25
- };
26
- };
27
- }
17
+ ) => Promise<Processed | undefined>;
28
18
 
29
19
  export interface Code {
30
20
  code: string;
@@ -44,6 +34,4 @@ export interface CompileData {
44
34
  lang: string;
45
35
  compiled: CompileResult;
46
36
  ssr: boolean | undefined;
47
- dependencies: string[];
48
- preprocessed: Processed;
49
37
  }
@@ -1,17 +1,9 @@
1
1
  import type { ResolvedOptions } from './options.d.ts';
2
2
  import type { IdFilter, IdParser } from './id.d.ts';
3
3
  import type { CompileSvelte } from './compile.d.ts';
4
- import type { Environment } from 'vite';
5
- // eslint-disable-next-line n/no-missing-import
6
- import { VitePluginSvelteCache } from '../utils/vite-plugin-svelte-cache.js';
7
-
8
- interface EnvContext {
9
- environment: Environment;
10
- }
11
4
 
12
5
  export interface PluginAPI {
13
6
  options: ResolvedOptions;
14
- getEnvironmentCache: (arg: EnvContext) => VitePluginSvelteCache;
15
7
  idFilter: IdFilter;
16
8
  idParser: IdParser;
17
9
  compileSvelte: CompileSvelte;
@@ -2,7 +2,6 @@ import * as svelte from 'svelte/compiler';
2
2
  import { safeBase64Hash } from './hash.js';
3
3
  import { log } from './log.js';
4
4
 
5
- import { checkPreprocessDependencies } from './preprocess.js';
6
5
  import { mapToRelative } from './sourcemaps.js';
7
6
  import { enhanceCompileError } from './error.js';
8
7
 
@@ -19,11 +18,9 @@ export function createCompileSvelte() {
19
18
  /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
20
19
  let stats;
21
20
  /** @type {import('../types/compile.d.ts').CompileSvelte} */
22
- return async function compileSvelte(svelteRequest, code, options, preprocessed) {
21
+ return async function compileSvelte(svelteRequest, code, options, sourcemap) {
23
22
  const { filename, normalizedFilename, cssId, ssr, raw } = svelteRequest;
24
23
  const { emitCss = true } = options;
25
- /** @type {string[]} */
26
- const dependencies = [];
27
24
  /** @type {import('svelte/compiler').Warning[]} */
28
25
  const warnings = [];
29
26
 
@@ -59,20 +56,6 @@ export function createCompileSvelte() {
59
56
  generate: ssr ? 'server' : 'client'
60
57
  };
61
58
 
62
- if (preprocessed) {
63
- if (preprocessed.dependencies?.length) {
64
- const checked = checkPreprocessDependencies(filename, preprocessed.dependencies);
65
- if (checked.warnings.length) {
66
- warnings.push(...checked.warnings);
67
- }
68
- if (checked.dependencies.length) {
69
- dependencies.push(...checked.dependencies);
70
- }
71
- }
72
-
73
- if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
74
- }
75
-
76
59
  let finalCode = code;
77
60
  if (compileOptions.hmr && options.emitCss) {
78
61
  const hash = `s-${safeBase64Hash(normalizedFilename)}`;
@@ -103,6 +86,9 @@ export function createCompileSvelte() {
103
86
  ...dynamicCompileOptions
104
87
  }
105
88
  : compileOptions;
89
+ if (sourcemap) {
90
+ finalCompileOptions.sourcemap = sourcemap;
91
+ }
106
92
  const endStat = stats?.start(filename);
107
93
  /** @type {import('svelte/compiler').CompileResult} */
108
94
  let compiled;
@@ -160,9 +146,7 @@ export function createCompileSvelte() {
160
146
  cssId,
161
147
  lang,
162
148
  compiled,
163
- ssr,
164
- dependencies,
165
- preprocessed: preprocessed ?? { code }
149
+ ssr
166
150
  };
167
151
  };
168
152
  }
@@ -26,6 +26,9 @@ export const SVELTE_EXPORT_CONDITIONS = ['svelte'];
26
26
  export const FAQ_LINK_MISSING_EXPORTS_CONDITION =
27
27
  'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition';
28
28
 
29
+ export const LINK_TRANSFORM_WITH_PLUGIN =
30
+ 'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/advanced-usage.md#transform-svelte-files-with-vite-plugins';
31
+
29
32
  export const DEFAULT_SVELTE_EXT = ['.svelte'];
30
33
  export const DEFAULT_SVELTE_MODULE_INFIX = ['.svelte.'];
31
34
  export const DEFAULT_SVELTE_MODULE_EXT = ['.js', '.ts'];
@@ -5,7 +5,8 @@ const {
5
5
  defaultServerMainFields,
6
6
  defaultClientConditions,
7
7
  defaultServerConditions,
8
- normalizePath
8
+ normalizePath,
9
+ searchForWorkspaceRoot
9
10
  } = vite;
10
11
  import { log } from './log.js';
11
12
  import { loadSvelteConfig } from './load-svelte-config.js';
@@ -429,6 +430,7 @@ async function buildExtraConfigForDependencies(options, config) {
429
430
  const packagesWithoutSvelteExportsCondition = new Set();
430
431
  const depsConfig = await crawlFrameworkPkgs({
431
432
  root: options.root,
433
+ workspaceRoot: searchForWorkspaceRoot(options.root),
432
434
  isBuild: options.isBuild,
433
435
  viteUserConfig: config,
434
436
  isFrameworkPkgByJson(pkgJson) {
@@ -461,11 +463,12 @@ async function buildExtraConfigForDependencies(options, config) {
461
463
  }
462
464
  });
463
465
  if (
466
+ !options.isBuild &&
464
467
  !options.experimental?.disableSvelteResolveWarnings &&
465
468
  packagesWithoutSvelteExportsCondition?.size > 0
466
469
  ) {
467
- log.warn(
468
- `WARNING: The following packages have a svelte field in their package.json but no exports condition for svelte.\n\n${[
470
+ log.info.once(
471
+ `The following packages have a svelte field in their package.json but no exports condition for svelte.\n\n${[
469
472
  ...packagesWithoutSvelteExportsCondition
470
473
  ].join('\n')}\n\nPlease see ${FAQ_LINK_MISSING_EXPORTS_CONDITION} for details.`
471
474
  );
@@ -1,5 +1,5 @@
1
1
  import { log } from './log.js';
2
- import { normalizePath } from 'vite';
2
+ import { LINK_TRANSFORM_WITH_PLUGIN } from './constants.js';
3
3
 
4
4
  /**
5
5
  * @param {import('../types/options.d.ts').ResolvedOptions} options
@@ -15,17 +15,24 @@ function buildExtraPreprocessors(options, config) {
15
15
  /** @type {import('svelte/compiler').PreprocessorGroup[]} */
16
16
  const appendPreprocessors = [];
17
17
 
18
- const pluginsWithPreprocessorsDeprecated = config.plugins.filter((p) => p.api?.sveltePreprocess);
19
- if (pluginsWithPreprocessorsDeprecated.length > 0) {
20
- log.warn(
21
- `The following plugins use the deprecated 'plugin.api.sveltePreprocess' field. Please contact their maintainers and ask them to use a vite plugin transform instead: ${pluginsWithPreprocessorsDeprecated
18
+ /** @type {import('vite').Plugin[]} */
19
+ const pluginsWithPreprocessors = config.plugins.filter((p) => p?.api?.sveltePreprocess);
20
+
21
+ if (
22
+ !options.isBuild &&
23
+ !options.experimental?.disableApiSveltePreprocessWarnings &&
24
+ pluginsWithPreprocessors.length > 0
25
+ ) {
26
+ log.info.once(
27
+ `The following plugins use the deprecated 'plugin.api.sveltePreprocess' field: ${pluginsWithPreprocessors
22
28
  .map((p) => p.name)
23
- .join(', ')}`
29
+ .join(', ')}
30
+ Please contact their maintainers and ask them to use a vite plugin transform instead.
31
+ See ${LINK_TRANSFORM_WITH_PLUGIN} for more information.
32
+ `.replace(/\t+/g, '\t')
24
33
  );
25
34
  }
26
35
  /** @type {import('vite').Plugin[]} */
27
- const pluginsWithPreprocessors = config.plugins.filter((p) => p?.api?.sveltePreprocess);
28
- /** @type {import('vite').Plugin[]} */
29
36
  const ignored = [];
30
37
  /** @type {import('vite').Plugin[]} */
31
38
  const included = [];
@@ -80,52 +87,3 @@ export function addExtraPreprocessors(options, config) {
80
87
  }
81
88
  }
82
89
  }
83
-
84
- /**
85
- *
86
- * @param filename {string}
87
- * @param dependencies {string[]}
88
- * @returns {({dependencies: string[], warnings:import('svelte/compiler').Warning[] })}
89
- */
90
- export function checkPreprocessDependencies(filename, dependencies) {
91
- /** @type {import('svelte/compiler').Warning[]} */
92
- const warnings = [];
93
-
94
- // to find self, we have to compare normalized filenames, but must keep the original values in `dependencies`
95
- // because otherwise file watching on windows doesn't work
96
- // so we track idx and filter by that in the end
97
- /** @type {number[]} */
98
- const selfIdx = [];
99
- const normalizedFullFilename = normalizePath(filename);
100
- const normalizedDeps = dependencies.map(normalizePath);
101
- for (let i = 0; i < normalizedDeps.length; i++) {
102
- if (normalizedDeps[i] === normalizedFullFilename) {
103
- selfIdx.push(i);
104
- }
105
- }
106
- const hasSelfDependency = selfIdx.length > 0;
107
- if (hasSelfDependency) {
108
- warnings.push({
109
- code: 'vite-plugin-svelte-preprocess-depends-on-self',
110
- message:
111
- 'svelte.preprocess returned this file as a dependency of itself. This can be caused by an invalid configuration or importing generated code that depends on .svelte files (eg. tailwind base css)',
112
- filename
113
- });
114
- }
115
-
116
- if (dependencies.length > 10) {
117
- warnings.push({
118
- code: 'vite-plugin-svelte-preprocess-many-dependencies',
119
- message: `svelte.preprocess depends on more than 10 external files which can cause slow builds and poor DX, try to reduce them. Found: ${dependencies.join(
120
- ', '
121
- )}`,
122
- filename
123
- });
124
- }
125
- return {
126
- dependencies: hasSelfDependency
127
- ? dependencies.filter((_, i) => !selfIdx.includes(i)) // remove self dependency
128
- : dependencies,
129
- warnings
130
- };
131
- }
@@ -5,30 +5,15 @@ 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.js').VitePluginSvelteCache} cache
9
8
  * @returns {void}
10
9
  */
11
- export function setupWatchers(options, cache) {
10
+ export function setupWatchers(options) {
12
11
  const { server, configFile: svelteConfigFile } = options;
13
12
  if (!server) {
14
13
  return;
15
14
  }
16
15
  const { watcher, ws } = server;
17
16
  const { root, server: serverConfig } = server.config;
18
- /** @type {(filename: string) => void} */
19
- const emitChangeEventOnDependants = (filename) => {
20
- const dependants = cache.getDependants(filename);
21
- dependants.forEach((dependant) => {
22
- if (fs.existsSync(dependant)) {
23
- log.debug(
24
- `emitting virtual change event for "${dependant}" because dependency "${filename}" changed`,
25
- undefined,
26
- 'hmr'
27
- );
28
- watcher.emit('change', dependant);
29
- }
30
- });
31
- };
32
17
 
33
18
  /** @type {(filename: string) => void} */
34
19
  const triggerViteRestart = (filename) => {
@@ -52,8 +37,8 @@ export function setupWatchers(options, cache) {
52
37
  /** @type {Record<string, Function[]>} */
53
38
  const listenerCollection = {
54
39
  add: [],
55
- change: [emitChangeEventOnDependants],
56
- unlink: [emitChangeEventOnDependants]
40
+ change: [],
41
+ unlink: []
57
42
  };
58
43
 
59
44
  if (svelteConfigFile !== false) {
package/types/index.d.ts CHANGED
@@ -173,6 +173,13 @@ declare module '@sveltejs/vite-plugin-svelte' {
173
173
  */
174
174
  disableSvelteResolveWarnings?: boolean;
175
175
 
176
+ /**
177
+ * disable api.sveltePreprocess deprecation warnings
178
+ *
179
+ * @default false
180
+ */
181
+ disableApiSveltePreprocessWarnings?: boolean;
182
+
176
183
  compileModule?: CompileModuleOptions;
177
184
  }
178
185
 
@@ -26,6 +26,6 @@
26
26
  null,
27
27
  null
28
28
  ],
29
- "mappings": ";;;;aAIYA,OAAOA;;WAETC,mBAAmBA;;;;;;;;;;;kBAWZC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAgGbC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiDnBC,mBAAmBA;;;;;;;;;;;;;;;;WAgBnBC,oBAAoBA;;;;;;;;;;;;;;;MAezBC,SAASA;;kBAEGC,qBAAqBA;;;;;;;;;;;;;;;;;;iBChLtBC,MAAMA;iBCMNC,cAAcA;iBCFRC,gBAAgBA",
29
+ "mappings": ";;;;aAIYA,OAAOA;;WAETC,mBAAmBA;;;;;;;;;;;kBAWZC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAgGbC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiDnBC,mBAAmBA;;;;;;;;;;;;;;;;;;;;;;;WAuBnBC,oBAAoBA;;;;;;;;;;;;;;;MAezBC,SAASA;;kBAEGC,qBAAqBA;;;;;;;;;;;;;;;;;;iBCvLtBC,MAAMA;iBCMNC,cAAcA;iBCFRC,gBAAgBA",
30
30
  "ignoreList": []
31
31
  }
@@ -1,153 +0,0 @@
1
- /**
2
- * @class
3
- */
4
- export class VitePluginSvelteCache {
5
- /** @type {Map<string, import('../types/compile.d.ts').Code | null>} */
6
- #css = new Map();
7
- /** @type {Map<string, import('../types/compile.d.ts').Code | null>} */
8
- #js = new Map();
9
- /** @type {Map<string, string[]>} */
10
- #dependencies = new Map();
11
- /** @type {Map<string, Set<string>>} */
12
- #dependants = new Map();
13
- /** @type {Map<string, any>} */
14
- #errors = new Map();
15
-
16
- /**
17
- * @param {import('../types/compile.d.ts').CompileData} compileData
18
- */
19
- update(compileData) {
20
- this.#errors.delete(compileData.normalizedFilename);
21
- this.#updateCSS(compileData);
22
- this.#updateJS(compileData);
23
- this.#updateDependencies(compileData);
24
- }
25
-
26
- /**
27
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
28
- * @returns {boolean}
29
- */
30
- has(svelteRequest) {
31
- const id = svelteRequest.normalizedFilename;
32
- return this.#errors.has(id) || this.#js.has(id) || this.#css.has(id);
33
- }
34
-
35
- /**
36
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
37
- * @param {any} error
38
- */
39
- setError(svelteRequest, error) {
40
- // keep dependency info, otherwise errors in dependants would not trigger an update after fixing
41
- // because they are no longer watched
42
- this.remove(svelteRequest, true);
43
- this.#errors.set(svelteRequest.normalizedFilename, error);
44
- }
45
-
46
- /**
47
- * @param {import('../types/compile.d.ts').CompileData} compileData
48
- */
49
- #updateCSS(compileData) {
50
- this.#css.set(compileData.normalizedFilename, compileData.compiled.css);
51
- }
52
-
53
- /**
54
- * @param {import('../types/compile.d.ts').CompileData} compileData
55
- */
56
- #updateJS(compileData) {
57
- if (!compileData.ssr) {
58
- // do not cache SSR js
59
- this.#js.set(compileData.normalizedFilename, compileData.compiled.js);
60
- }
61
- }
62
-
63
- /**
64
- * @param {import('../types/compile.d.ts').CompileData} compileData
65
- */
66
- #updateDependencies(compileData) {
67
- const id = compileData.normalizedFilename;
68
- const prevDependencies = this.#dependencies.get(id) || [];
69
- const dependencies = compileData.dependencies;
70
- this.#dependencies.set(id, dependencies);
71
- const removed = prevDependencies.filter((d) => !dependencies.includes(d));
72
- const added = dependencies.filter((d) => !prevDependencies.includes(d));
73
- added.forEach((d) => {
74
- if (!this.#dependants.has(d)) {
75
- this.#dependants.set(d, new Set());
76
- }
77
- /** @type {Set<string>} */ (this.#dependants.get(d)).add(compileData.filename);
78
- });
79
- removed.forEach((d) => {
80
- /** @type {Set<string>} */ (this.#dependants.get(d)).delete(compileData.filename);
81
- });
82
- }
83
-
84
- /**
85
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
86
- * @param {boolean} [keepDependencies]
87
- * @returns {boolean}
88
- */
89
- remove(svelteRequest, keepDependencies = false) {
90
- const id = svelteRequest.normalizedFilename;
91
- let removed = false;
92
- if (this.#errors.delete(id)) {
93
- removed = true;
94
- }
95
- if (this.#js.delete(id)) {
96
- removed = true;
97
- }
98
- if (this.#css.delete(id)) {
99
- removed = true;
100
- }
101
- if (!keepDependencies) {
102
- const dependencies = this.#dependencies.get(id);
103
- if (dependencies) {
104
- removed = true;
105
- dependencies.forEach((d) => {
106
- const dependants = this.#dependants.get(d);
107
- if (dependants && dependants.has(svelteRequest.filename)) {
108
- dependants.delete(svelteRequest.filename);
109
- }
110
- });
111
- this.#dependencies.delete(id);
112
- }
113
- }
114
-
115
- return removed;
116
- }
117
-
118
- /**
119
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
120
- * @returns {import('../types/compile.d.ts').Code | undefined | null}
121
- */
122
- getCSS(svelteRequest) {
123
- return this.#css.get(svelteRequest.normalizedFilename);
124
- }
125
-
126
- /**
127
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
128
- * @returns {import('../types/compile.d.ts').Code | undefined | null}
129
- */
130
- getJS(svelteRequest) {
131
- if (!svelteRequest.ssr) {
132
- // SSR js isn't cached
133
- return this.#js.get(svelteRequest.normalizedFilename);
134
- }
135
- }
136
-
137
- /**
138
- * @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
139
- * @returns {any}
140
- */
141
- getError(svelteRequest) {
142
- return this.#errors.get(svelteRequest.normalizedFilename);
143
- }
144
-
145
- /**
146
- * @param {string} path
147
- * @returns {string[]}
148
- */
149
- getDependants(path) {
150
- const dependants = this.#dependants.get(path);
151
- return dependants ? [...dependants] : [];
152
- }
153
- }