Skip to content

Commit 75917ee

Browse files
authored
docs: migration page (#8739)
1 parent 0eca1c7 commit 75917ee

File tree

2 files changed

+156
-5
lines changed

2 files changed

+156
-5
lines changed

documentation/docs/05-misc/04-migrating-v3-to-v4.md

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
---
2+
title: Svelte 4 migration guide
3+
---
4+
5+
This migration guide provides an overview of how to migrate from Svelte version 3 to 4. See the linked PRs for more details about each change. Use the migration script to migrate some of these automatically: `npx svelte-migrate svelte-4`
6+
7+
If you're a library author, consider whether to only support Svelte 4 or if it's possible to support Svelte 3 too. Since most of the breaking changes don't affect many people, this may be easily possible. Also remember to update the version range in your `peerDependencies`.
8+
9+
## Minimum version requirements
10+
11+
- Upgrade to Node 16 or higher. Earlier versions are no longer supported. ([#8566](https://github.com/sveltejs/svelte/issues/8566))
12+
- If you are using SvelteKit, upgrade to 1.20.4 or newer ([sveltejs/kit#10172](https://github.com/sveltejs/kit/pull/10172))
13+
- If you are using Vite without SvelteKit, upgrade to `vite-plugin-svelte` 2.4.1 or newer ([#8516](https://github.com/sveltejs/svelte/issues/8516))
14+
- If you are using webpack, upgrade to webpack 5 or higher. Earlier versions are no longer supported. ([#8515](https://github.com/sveltejs/svelte/issues/8515))
15+
- If you are using TypeScript, upgrade to TypeScript 5 or higher. Lower versions might still work, but no guarantees are made about that. ([#8488](https://github.com/sveltejs/svelte/issues/8488))
16+
17+
## Browser conditions for bundlers
18+
19+
Bundlers must now specify the browser condition when building a frontend bundle for the browser. SvelteKit and Vite will handle this automatically for you. For Rollup or webpack you may need to adjust your config to ensure it matches what is shown in the [`rollup-plugin-svelte`](https://github.com/sveltejs/rollup-plugin-svelte/#usage) and [`svelte-loader`](https://github.com/sveltejs/svelte-loader#usage) documentation. ([#8516](https://github.com/sveltejs/svelte/issues/8516))
20+
21+
## Removal of CJS related output
22+
23+
Svelte no longer supports the CommonJS (CJS) format for compiler output and has also removed the `svelte/register` hook and the CJS runtime version. If you need to stay on the CJS output format, consider using a bundler to convert Svelte's ESM output to CJS in a post-build step. ([#8613](https://github.com/sveltejs/svelte/issues/8613))
24+
25+
## Stricter types for Svelte functions
26+
27+
There are now stricter types for `createEventDispatcher`, `Action`, `ActionReturn`, and `onMount`:
28+
29+
- `createEventDispatcher` now supports specifying that a payload is optional, required, or non-existent, and the call sites are checked accordingly ([#7224](https://github.com/sveltejs/svelte/issues/7224))
30+
31+
```ts
32+
// @errors: 2554 2345
33+
import { createEventDispatcher } from 'svelte';
34+
35+
// Svelte version 3:
36+
const dispatch = createEventDispatcher<{
37+
optional: number | null;
38+
required: string;
39+
noArgument: never;
40+
}>();
41+
42+
dispatch('optional');
43+
dispatch('required'); // I can still omit the detail argument
44+
dispatch('noArgument', 'surprise'); // I can still add a detail argument
45+
46+
// Svelte version 4 using TypeScript strict mode:
47+
dispatch('optional');
48+
dispatch('required'); // error, missing argument
49+
dispatch('noArgument', 'surprise'); // error, cannot pass an argument
50+
```
51+
52+
- `Action` and `ActionReturn` have a default parameter type of `never` now, which means you need to type the generic if you want to specify that this action receives a parameter. The migration script will migrate this automatically ([#7442](https://github.com/sveltejs/svelte/pull/7442))
53+
54+
```diff
55+
-const action: Action = (node, params) => { .. } // this is now an error, as params is expected to not exist
56+
+const action: Action<HTMLElement, string> = (node, params) => { .. } // params is of type string
57+
```
58+
59+
- `onMount` now shows a type error if you return a function asynchronously from it, because this is likely a bug in your code where you expect the callback to be called on destroy, which it will only do for synchronously returned functions ([#8136](https://github.com/sveltejs/svelte/issues/8136))
60+
61+
```diff
62+
// Example where this change reveals an actual bug
63+
onMount(
64+
- // someCleanup() not called because function handed to onMount is async
65+
- async () => {
66+
- const something = await foo();
67+
+ // someCleanup() is called because function handed to onMount is sync
68+
+ () => {
69+
+ foo().then(something => ..
70+
// ..
71+
return () => someCleanup();
72+
}
73+
);
74+
```
75+
76+
## Custom Elements with Svelte
77+
78+
The creation of custom elements with Svelte has been overhauled and significantly improved. The `tag` option is deprecated in favor of the new `customElement` option:
79+
80+
```diff
81+
-<svelte:options tag="my-component" />
82+
+<svelte:options customElement="my-component" />
83+
```
84+
85+
This change was made to allow [more configurability](custom-elements-api#component-options) for advanced use cases. The migration script will adjust your code automatically. The update timing of properties has changed slightly as well. ([#8457](https://github.com/sveltejs/svelte/issues/8457))
86+
87+
## SvelteComponentTyped is deprecated
88+
89+
`SvelteComponentTyped` is deprecated, as `SvelteComponent` now has all its typing capabilities. Replace all instances of `SvelteComponentTyped` with `SvelteComponent`.
90+
91+
```diff
92+
- import { SvelteComponentTyped } from 'svelte';
93+
+ import { SvelteComponent } from 'svelte';
94+
95+
- export class Foo extends SvelteComponentTyped<{ aProp: string }> {}
96+
+ export class Foo extends SvelteComponent<{ aProp: string }> {}
97+
```
98+
99+
If you have used `SvelteComponent` as the component instance type previously, you may see a somewhat opaque type error now, which is solved by changing `: typeof SvelteComponent` to `: typeof SvelteComponent<any>`.
100+
101+
```diff
102+
<script>
103+
import ComponentA from './ComponentA.svelte';
104+
import ComponentB from './ComponentB.svelte';
105+
import { SvelteComponent } from 'svelte';
106+
107+
- let component: typeof SvelteComponent;
108+
+ let component: typeof SvelteComponent<any>;
109+
110+
function choseRandomly() {
111+
component = Math.random() > 0.5 ? ComponentA : ComponentB;
112+
}
113+
</script>
114+
115+
<button on:click={choseRandomly}>random</button>
116+
<svelte:element this={component} />
117+
```
118+
119+
The migration script will do both automatically for you. ([#8512](https://github.com/sveltejs/svelte/issues/8512))
120+
121+
## Transitions are local by default
122+
123+
Transitions are now local by default to prevent confusion around page navigations. To make them global, add the `|global` modifier. The migration script will do this automatically for you. ([#6686](https://github.com/sveltejs/svelte/issues/6686))
124+
125+
## Default slot bindings
126+
127+
Default slot bindings are no longer exposed to named slots and vice versa:
128+
129+
```svelte
130+
<script>
131+
import Nested from './Nested.svelte';
132+
</script>
133+
134+
<Nested let:count>
135+
<p>
136+
count in default slot - is available: {count}
137+
</p>
138+
<p slot="bar">
139+
count in bar slot - is not available: {count}
140+
</p>
141+
</Nested>
142+
```
143+
144+
This makes slot bindings more consistent as the behavior is undefined when for example the default slot is from a list and the named slot is not. ([#6049](https://github.com/sveltejs/svelte/issues/6049))
145+
146+
## Preprocessors
147+
148+
The order in which preprocessors are applied has changed. Now, preprocessors are executed in order, and within one group, the order is markup, script, style. Each preprocessor must also have a name. ([#8618](https://github.com/sveltejs/svelte/issues/8618))
149+
150+
## Other breaking changes
151+
152+
- the `inert` attribute is now applied to outroing elements to make them invisible to assistive technology and prevent interaction. ([#8628](https://github.com/sveltejs/svelte/pull/8628))
153+
- the runtime now uses `classList.toggle(name, boolean)` which may not work in very old browsers. Consider using a [polyfill](https://github.com/eligrey/classList.js) if you need to support these browsers. ([#8629](https://github.com/sveltejs/svelte/issues/8629))
154+
- people implementing their own stores from scratch using the `StartStopNotifier` interface (which is passed to the create function of `writable` etc) from `svelte/store` now need to pass an update function in addition to the set function. This has no effect on people using stores or creating stores using the existing Svelte stores. ([#6750](https://github.com/sveltejs/svelte/issues/6750))
155+
- `derived` will now throw an error on falsy values instead of stores passed to it. ([#7947](https://github.com/sveltejs/svelte/issues/7947))
156+
- type definitions for `svelte/internal` were removed to further discourage usage of those internal methods which are not public API. Most of these will likely change for Svelte 5

0 commit comments

Comments
 (0)