Skip to content

Commit 1011098

Browse files
authored
refactor: bump svelte and remove custom cssHash handling (#1271)
* refactor: bump svelte and remove custom cssHash handling * chore: add warning message and update cssHash faq * chore: update FAQ link * fix: formatting and simplify message * update changeset * chore: bump minimum svelte version to 5.46.4 to get a security fix
1 parent 7e39bc1 commit 1011098

File tree

10 files changed

+59
-63
lines changed

10 files changed

+59
-63
lines changed

.changeset/six-trees-scream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': major
3+
---
4+
5+
breaking(dev): no longer overrides compilerOptions.cssHash because Svelte now produces a stable css hash by itself

.changeset/wild-hairs-fetch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': major
3+
---
4+
5+
breaking(deps): require svelte 5.46.4 or later

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ jobs:
126126
- name: downgrade svelte to baseline
127127
if: matrix.svelte == 'baseline'
128128
run: |
129-
pnpm update -r --no-save svelte@5.0.0
129+
pnpm update -r --no-save svelte@5.46.4
130130
pnpm ls svelte
131131
- name: install playwright chromium
132132
run: pnpm playwright install chromium --only-shell

docs/faq.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,24 @@ Bad:
5454
<script type="text/typescript"></script>
5555
```
5656

57-
### Why can't `cssHash` be set in development mode?
57+
### Why should `cssHash` be calculated from filename during dev
5858

59-
`cssHash` is fixed in development for CSS HMR in Svelte components, ensuring that the hash value is stable based on the file name so that styles are only updated when changed.
59+
The output of this function is part of the js module for the component. If the hash changes when css changes, every css update also triggers a js update.
60+
These js updates can lead to application state resetting in your browser, which is a worse developer experience than only css updating.
61+
It must also be different between different components to ensure that styles are scoped and updates applied correctly.
6062

61-
However, `cssHash` is respected in production builds as HMR is a dev-only feature.
63+
So it is recommended to keep the pattern defined by Svelte itself. If you want to customize the prefix, use this:
64+
65+
```js
66+
// svelte.config.js
67+
export default {
68+
compilerOptions: {
69+
cssHash: ({ hash, filename, css }) => `my-custom-prefix-${hash(filename ?? css)}`
70+
}
71+
};
72+
```
73+
74+
If you don't want the hash to depend on filename, either accept the worse dx or customize cssHash only during build.
6275
6376
### How do I add a Svelte preprocessor from a Vite plugin?
6477

packages/vite-plugin-svelte/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"vitefu": "^1.1.1"
4646
},
4747
"peerDependencies": {
48-
"svelte": "^5.0.0",
48+
"svelte": "^5.46.4",
4949
"vite": "^8.0.0-beta.7 || ^8.0.0"
5050
},
5151
"devDependencies": {

packages/vite-plugin-svelte/src/plugins/setup-optimizer.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import path from 'node:path';
33
import * as svelte from 'svelte/compiler';
44
import { log } from '../utils/log.js';
55
import { toRollupError } from '../utils/error.js';
6-
import { safeBase64Hash } from '../utils/hash.js';
7-
import { normalize } from '../utils/id.js';
86

97
/**
108
* @typedef {NonNullable<import('vite').Rollup.Plugin>} RollupPlugin
@@ -136,11 +134,6 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
136134
generate: 'client'
137135
};
138136

139-
if (compileOptions.hmr && options.emitCss) {
140-
const hash = `s-${safeBase64Hash(normalize(filename, options.root))}`;
141-
compileOptions.cssHash = () => hash;
142-
}
143-
144137
let preprocessed;
145138

146139
if (options.preprocess) {

packages/vite-plugin-svelte/src/utils/compile.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as svelte from 'svelte/compiler';
2-
import { safeBase64Hash } from './hash.js';
32
import { log } from './log.js';
43

54
import { mapToRelative } from './sourcemaps.js';
@@ -58,8 +57,6 @@ export function createCompileSvelte() {
5857

5958
let finalCode = code;
6059
if (compileOptions.hmr && options.emitCss) {
61-
const hash = `s-${safeBase64Hash(normalizedFilename)}`;
62-
compileOptions.cssHash = () => hash;
6360
const closeStylePos = code.lastIndexOf('</style>');
6461
if (closeStylePos > -1) {
6562
// inject rule that forces compile to attach scope class to every node in the template

packages/vite-plugin-svelte/src/utils/constants.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ export const SVELTE_IMPORTS = Object.entries(sveltePkg.exports)
2323

2424
export const SVELTE_EXPORT_CONDITIONS = ['svelte'];
2525

26-
export const FAQ_LINK_MISSING_EXPORTS_CONDITION =
27-
'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition';
26+
const FAQ_URL = 'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md';
27+
export const FAQ_LINK_MISSING_EXPORTS_CONDITION = `${FAQ_URL}#missing-exports-condition`;
28+
export const FAQ_LINK_CSSHASH = `${FAQ_URL}#why-should-csshash-be-calculated-from-filename-during-dev`;
2829

2930
export const LINK_TRANSFORM_WITH_PLUGIN =
3031
'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/advanced-usage.md#transform-svelte-files-with-vite-plugins';

packages/vite-plugin-svelte/src/utils/hash.js

Lines changed: 0 additions & 43 deletions
This file was deleted.

packages/vite-plugin-svelte/src/utils/options.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { log } from './log.js';
1212
import { loadSvelteConfig } from './load-svelte-config.js';
1313
import {
1414
DEFAULT_SVELTE_EXT,
15+
FAQ_LINK_CSSHASH,
1516
FAQ_LINK_MISSING_EXPORTS_CONDITION,
1617
SVELTE_EXPORT_CONDITIONS,
1718
SVELTE_IMPORTS,
@@ -243,6 +244,33 @@ function enforceOptionsForHmr(options, viteConfig) {
243244
);
244245
options.compilerOptions.hmr = false;
245246
}
247+
248+
if (
249+
options.isServe &&
250+
options.compilerOptions.hmr &&
251+
options.emitCss &&
252+
options.compilerOptions.cssHash
253+
) {
254+
let usesFilename = false;
255+
let usesCss = false;
256+
options.compilerOptions.cssHash({
257+
get filename() {
258+
usesFilename = true;
259+
return 'Foo.svelte';
260+
},
261+
get css() {
262+
usesCss = true;
263+
return '.foo{}';
264+
},
265+
name: 'Foo',
266+
hash: /** @type{(x: string) => string} */ (x) => x
267+
});
268+
if (!usesFilename || usesCss) {
269+
log.warn(
270+
`The custom compilerOptions.cssHash in your svelte config can degrade your DX. See ${FAQ_LINK_CSSHASH} for more information.`
271+
);
272+
}
273+
}
246274
}
247275

248276
/**
@@ -270,9 +298,6 @@ function enforceOptionsForProduction(options) {
270298
*/
271299
function removeIgnoredOptions(options) {
272300
const ignoredCompilerOptions = ['generate', 'format', 'filename'];
273-
if (options.compilerOptions.hmr && options.emitCss) {
274-
ignoredCompilerOptions.push('cssHash');
275-
}
276301
const passedCompilerOptions = Object.keys(options.compilerOptions || {});
277302
const passedIgnored = passedCompilerOptions.filter((o) => ignoredCompilerOptions.includes(o));
278303
if (passedIgnored.length) {

0 commit comments

Comments
 (0)