@rsvelte/vite-plugin-svelte 0.4.2 → 0.5.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/README.md CHANGED
@@ -5,13 +5,27 @@ by the Rust [rsvelte](https://github.com/baseballyama/rsvelte) compiler. It is a
5
5
  fork of the official [`@sveltejs/vite-plugin-svelte`](https://github.com/sveltejs/vite-plugin-svelte)
6
6
  whose compile / preprocess / HMR calls route through the rsvelte compiler (via
7
7
  [`@rsvelte/vite-plugin-svelte-native`](https://www.npmjs.com/package/@rsvelte/vite-plugin-svelte-native))
8
- instead of `svelte/compiler`, so you can build a Vite or SvelteKit app on the
9
- Rust toolchain with the same plugin surface.
8
+ instead of `svelte/compiler` — a drop-in replacement with the same plugin surface.
10
9
 
11
- > **⚠️ Early stage.** A drop-in replacement for `@sveltejs/vite-plugin-svelte`,
12
- > but treat it as experimental. Supports Vite 6, 7 and 8.
10
+ > **⚠️ Early stage.** Treat it as experimental.
13
11
 
14
- ## Install
12
+ The Rust compiler ships as a native binding via `optionalDependencies` and is
13
+ resolved automatically for your platform.
14
+
15
+ **Compatibility:** Svelte `^5.0.0`, Vite `6.3+`, `7`, or `8`.
16
+
17
+ ## Which setup are you using?
18
+
19
+ | Setup | How to wire it up |
20
+ | --- | --- |
21
+ | **Plain Vite + Svelte** — you call `svelte()` yourself in `vite.config` | [(A) Import the plugin directly](#a-plain-vite--svelte) |
22
+ | **SvelteKit** — your `vite.config` only has `sveltekit()` | [(B) Alias it with a package-manager override](#b-sveltekit) |
23
+
24
+ If you are on SvelteKit, do **not** add `svelte()` to your plugins list — see (B).
25
+
26
+ ## (A) Plain Vite + Svelte
27
+
28
+ Install the plugin:
15
29
 
16
30
  ```bash
17
31
  npm install -D @rsvelte/vite-plugin-svelte
@@ -19,10 +33,7 @@ npm install -D @rsvelte/vite-plugin-svelte
19
33
  # yarn add -D @rsvelte/vite-plugin-svelte
20
34
  ```
21
35
 
22
- The Rust compiler is pulled in as a native binding via `optionalDependencies`,
23
- resolved automatically for your platform.
24
-
25
- ## Usage
36
+ Add it to your Vite config:
26
37
 
27
38
  ```js
28
39
  // vite.config.js
@@ -38,7 +49,7 @@ export default defineConfig({
38
49
  });
39
50
  ```
40
51
 
41
- The plugin exposes the same API as the official plugin, including
52
+ The package exposes the same API as the official plugin, including
42
53
  `vitePreprocess` and `loadSvelteConfig`:
43
54
 
44
55
  ```js
@@ -53,6 +64,65 @@ export default {
53
64
  };
54
65
  ```
55
66
 
67
+ ## (B) SvelteKit
68
+
69
+ In a SvelteKit app your `vite.config` only lists `sveltekit()`, and the Svelte
70
+ plugin is loaded **from inside `@sveltejs/kit`** under the package name
71
+ `@sveltejs/vite-plugin-svelte` — it never appears in your config. So the way to
72
+ swap in rsvelte is to redirect that package's module resolution with a
73
+ package-manager override (alias), not to touch `vite.config` at all.
74
+
75
+ Add the override to your `package.json`, then reinstall:
76
+
77
+ ```jsonc
78
+ // pnpm
79
+ {
80
+ "pnpm": {
81
+ "overrides": {
82
+ "@sveltejs/vite-plugin-svelte": "npm:@rsvelte/vite-plugin-svelte@^0.4.1"
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ ```jsonc
89
+ // npm
90
+ {
91
+ "overrides": {
92
+ "@sveltejs/vite-plugin-svelte": "npm:@rsvelte/vite-plugin-svelte@^0.4.1"
93
+ }
94
+ }
95
+ ```
96
+
97
+ ```jsonc
98
+ // yarn (v1 and Berry)
99
+ {
100
+ "resolutions": {
101
+ "@sveltejs/vite-plugin-svelte": "npm:@rsvelte/vite-plugin-svelte@^0.4.1"
102
+ }
103
+ }
104
+ ```
105
+
106
+ Because the override targets the package name, it also redirects the
107
+ `import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'` in your
108
+ `svelte.config.js` to the rsvelte version — no change needed there either.
109
+
110
+ ### Don't do this
111
+
112
+ ```js
113
+ // vite.config.js — ❌ WRONG
114
+ import { sveltekit } from '@sveltejs/kit/vite';
115
+ import { svelte } from '@rsvelte/vite-plugin-svelte';
116
+
117
+ export default {
118
+ plugins: [sveltekit(), svelte()] // two Svelte plugins → double compilation
119
+ };
120
+ ```
121
+
122
+ `sveltekit()` already loads the Svelte plugin internally. Adding `svelte()`
123
+ alongside it registers a second one, so every component compiles twice. Use the
124
+ override in (B) instead.
125
+
56
126
  ## Documentation
57
127
 
58
128
  Because this is a fork of `@sveltejs/vite-plugin-svelte`, the upstream
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsvelte/vite-plugin-svelte",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "license": "MIT",
5
5
  "author": "dominikg",
6
6
  "files": [
@@ -39,7 +39,7 @@
39
39
  "magic-string": "^1.0.0",
40
40
  "obug": "^2.1.0",
41
41
  "vitefu": "^1.1.1",
42
- "@rsvelte/vite-plugin-svelte-native": "^0.2.7"
42
+ "@rsvelte/vite-plugin-svelte-native": "^0.3.0"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "svelte": "^5.0.0",
@@ -201,7 +201,8 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
201
201
 
202
202
  if (compileOptions.hmr && options.emitCss) {
203
203
  const hash = `s-${safeBase64Hash(normalize(filename, options.root))}`;
204
- compileOptions.cssHash = () => hash;
204
+ compileOptions.cssHashOverride = hash;
205
+ delete compileOptions.cssHash;
205
206
  }
206
207
 
207
208
  let preprocessed;
@@ -239,7 +240,11 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
239
240
  }
240
241
  : compileOptions;
241
242
  const endStat = statsCollection?.start(filename);
242
- const compiled = svelte.compile(finalCode, finalCompileOptions);
243
+ // A dynamic cssHash function only works through the async callback bridge.
244
+ const compiled =
245
+ typeof finalCompileOptions.cssHash === 'function'
246
+ ? await svelte.compileAsync(finalCode, finalCompileOptions)
247
+ : svelte.compile(finalCode, finalCompileOptions);
243
248
  if (endStat) {
244
249
  endStat();
245
250
  }
@@ -59,7 +59,12 @@ export function createCompileSvelte() {
59
59
  let finalCode = code;
60
60
  if (compileOptions.hmr && options.emitCss) {
61
61
  const hash = `s-${safeBase64Hash(normalizedFilename)}`;
62
- compileOptions.cssHash = () => hash;
62
+ // Constant hash keeps the css scope class stable across HMR updates; the
63
+ // override path skips the cssHash callback bridge entirely. Drop any user
64
+ // cssHash so the override is the sole hash source (matches upstream, which
65
+ // overwrites cssHash here).
66
+ compileOptions.cssHashOverride = hash;
67
+ delete compileOptions.cssHash;
63
68
  const closeStylePos = code.lastIndexOf('</style>');
64
69
  if (closeStylePos > -1) {
65
70
  // inject rule that forces compile to attach scope class to every node in the template
@@ -93,7 +98,12 @@ export function createCompileSvelte() {
93
98
  /** @type {import('@rsvelte/vite-plugin-svelte-native').CompileResult} */
94
99
  let compiled;
95
100
  try {
96
- compiled = svelte.compile(finalCode, { ...finalCompileOptions, filename });
101
+ // A dynamic cssHash function only works through the async callback
102
+ // bridge; everything else stays on the faster synchronous path.
103
+ compiled =
104
+ typeof finalCompileOptions.cssHash === 'function'
105
+ ? await svelte.compileAsync(finalCode, { ...finalCompileOptions, filename })
106
+ : svelte.compile(finalCode, { ...finalCompileOptions, filename });
97
107
 
98
108
  // patch output with partial accept until svelte does it
99
109
  // TODO remove later