Ce guide de migration fournit un aperçu de la manière dont vous devez migrer une application en Svelte 3 vers Svelte 4. Allez voir les PRs associées pour plus de détails au sujet de chaque changement. Utilisez le script de migration pour migrer certains de ces changements automatiquement : npx svelte-migrate@latest svelte-4
.
Si vous êtes l'auteur d'une librairie, considérez bien le choix de ne supporter que Svelte 4 ou, si cela est possible, de continuer à supporter Svelte 3 également. Comme la plupart des changements non réversibles n'affectent que peu de personnes, cela est facilement faisable la plupart du temps. Enfin, n'oubliez pas de mettre à jour la plage de versions des peerDependencies
.
Exigences minimales pour Svelte 4permalink
- Mettez à jour vers Node 16 ou plus. Les versions précédentes ne sont plus supportées. (#8566)
- Si vous utilisez SvelteKit, mettez à jour sa version à 1.20.4 ou plus (sveltejs/kit#10172)
- Si vous utilisez Vite sans SvelteKit, mettez à jour la version de
vite-plugin-svelte
à 2.4.1 ou plus (#8516) - Si vous utilisez webpack, mettez à jour sa version à 5 ou plus et
svelte-loader
à 3.1.8 ou plus. Les versions précédentes ne sont plus supportées. (#8515, 198dbcf) - Si vous utilisez Rollup, mettez à jour la version de
rollup-plugin-svelte
à 7.1.5 ou plus (198dbcf) - Si vous utilisez TypeScript, mettez à jour sa version à 5.0.0 ou plus. Les versions précédentes pourront probablement toujours fonctionner, mais nous ne pouvons pas le garantir. (#8488)
Conditions de navigateurs pour les bundlerspermalink
Les bundlers doivent maintenant spécifier la condition browser
lorsque vous créez un bundler frontend pour le navigateur. SvelteKit et Vite se chargeront de le préciser pour vous automatiquement. Si vous utilisez un autre bundler, il se peut que les callbacks de cycle de vie comme onMount
ne s'exécutent pas correctement, et vous devrez mettre à jour la configuration de la résolution de module.
- Pour Rollup, vous pouvez faire cela dans le plugin
@rollup/plugin-node-resolve
en choisissantbrowser: true
dans ses options. Voir la documentation derollup-plugin-svelte
pour plus de détail - Pour Webpack, vous pouvez faire cela en ajoutant
"browser"
au tableauconditionNames
. Vous pourriez aussi avoir à mettre à jour votre configuration d'alias
, si vous vous en servez. Voir la documentation desvelte-loader
pour plus de détail
(#8516)
Suppression des sorties de build en CJSpermalink
Svelte ne supporte plus le format CommonJS (CJS) comme format de sortie de la compilation. L'API svelte/register
a été retirée ainsi que la version de runtime CJS. Si vous avez besoin de garder le format de sortie CJS, utilisez un bundler pour convertir la sortie ESM en CJS avec une étape de post-build. (#8613)
Typage plus strict pour les fonctions Sveltepermalink
Il y a maintenant des types plus stricts pour createEventDispatcher
, Action
, ActionReturn
et onMount
:
createEventDispatcher
supporte maintenant de pouvoir spécifier que son argument soit optionnel, obligatoire, ou simplement non défini ; les appels seront vérifiés en conséquence (#7224) :
ts
import {createEventDispatcher } from 'svelte';constdispatch =createEventDispatcher <{optional : number | null;required : string;noArgument : null;}>();Expected 2-3 arguments, but got 1.2554Expected 2-3 arguments, but got 1.Argument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.2345Argument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.// Svelte version 3:dispatch ('optional');dispatch ('required'); // Il est possible de ne pas spécifier l'argument de détailExpected 2-3 arguments, but got 1.2554Expected 2-3 arguments, but got 1.dispatch ('noArgument', 'surprise'); // Il est possible de spécifier un argument de détailArgument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.2345Argument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.// Svelte version 4 en utilisant le TypeScript avec le mode strict:dispatch ('optional');dispatch ('required'); // erreur, argument manquant (error, missing argument)dispatch ('noArgument', 'surprise'); // erreur, il n'est pas possible de passer un argument (error, cannot pass an argument)
Action
etActionReturn
ont maintenant un type d'argument par défaut àundefined
, ce qui signifie que vous devez typer le generic si vous voulez spécifier que cette action reçoit un paramètre. Le script de migration prendra cette règle en compte automatiquement (#7442)
const action: Action = (node, params) => { .. } // ceci lèvera maintenant une erreur si vous utilisez un paramètre
const action: Action<HTMLElement, string> = (node, params) => { .. } // params est maintenant de type string
onMount
affichera maintenant une erreur de typage si vous retournez une fonction asynchrone. En effet, cela est probablement un bug dans votre code pour lequel vous vous attendez à ce que le callback soit appelé à la destruction du composant, ce qui n'est le cas que pour des fonctions synchrones (#8136)
// Exemple pour lequel ce changement révèle un vrai bug
onMount(
// someCleanup() n'est pas appelé car la fonction passée à onMount est asynchrone
async () => {
const something = await foo();
// someCleanup() est appelé car la fonction passée à onMount est synchrone
() => {
foo().then(something => ..
// ..
return () => someCleanup();
}
);
Les Custom Elements avec Sveltepermalink
La création des Custom Elements (ou Web Components) avec Svelte a complètement été repensée et significativement améliorée. L'option tag
a été dépréciée en faveur de la nouvelle option customElement
:
<svelte:options tag="my-component" />
<svelte:options customElement="my-component" />
Ce changement est intervenu pour permettre une meilleure configuration pour des cas d'usages avancés. Le code de migration ajustera votre code automatiquement. La temporalité des changements des propriétés a également légèrement changée. (#8457)
SvelteComponentTyped est dépréciépermalink
SvelteComponentTyped
est déprécié, car SvelteComponent
contient tout le typage nécessaire. Remplacez toutes les instances de SvelteComponentTyped
par SvelteComponent
.
import { SvelteComponentTyped } from 'svelte';
import { SvelteComponent } from 'svelte';
export class Foo extends SvelteComponentTyped<{ aProp: string }> {}
export class Foo extends SvelteComponent<{ aProp: string }> {}
Si par le passé vous utilisiez SvelteComponent
comme type d'instance de composant, vous pourriez maintenant voir une erreur de type obscure, qui est résolue en changeant : typeof SvelteComponent
par : typeof SvelteComponent<any>
.
<script>
import ComponentA from './ComponentA.svelte';
import ComponentB from './ComponentB.svelte';
import { SvelteComponent } from 'svelte';
let component: typeof SvelteComponent;
let component: typeof SvelteComponent<any>;
function choseRandomly() {
component = Math.random() > 0.5 ? ComponentA : ComponentB;
}
</script>
<button on:click={choseRandomly}>aléatoire</button>
<svelte:element this={component} />
Le script de migration changera les deux cas automatiquement pour vous. (#8512)
Les transitions sont locales par défautpermalink
Les transitions sont désormais locales par défaut afin d'éviter toute confusion lors de la navigation dans les pages. "Local" signifie qu'une transition ne sera pas jouée si elle se trouve dans un bloc de contrôle imbriqué (each/if/await/key
) et non dans le bloc parent direct, mais qu'un bloc au-dessus soit créé ou détruit. Dans l'exemple suivant, l'animation d'introduction slide
ne sera jouée que lorsque success
passera de false
à true
, mais elle ne sera pas jouée lorsque show
passera de false
à true
:
{#if show}
...
{#if success}
<p in:slide>Succès</p>
{/each}
{/if}
Pour rendre les transitions globales, ajoutez le modificateur |global
- elles seront alors jouées lorsque n'importe quel bloc de flux de contrôle ci-dessus est créé ou détruit. Le script de migration le fera automatiquement pour vous. (#6686)
Les binding de slot par défautpermalink
Les liaisons de slots par défaut ne sont plus exposées aux slots nommés et vice versa :
<script>
import Nested from './Nested.svelte';
</script>
<Nested let:count>
<p>
count dans un slot par défaut - est accessible : {count}
</p>
<p slot="bar">
count dans un slot nommé (bar) - n'est pas accessible: {count}
</p>
</Nested>
Cela rend les liaisons de slots plus cohérentes car le comportement est indéfini lorsque, par exemple, le slot par défaut provient d'une liste et que le slot nommé n'en fait pas partie. (#6049)
Préprocesseurspermalink
L'ordre dans lequel les préprocesseurs sont appliqués a changé. Désormais, les préprocesseurs sont exécutés dans l'ordre et, au sein d'un même groupe, l'ordre est le suivant : balisage, script, style.
ts
import {preprocess } from 'svelte/compiler';const {code } = awaitpreprocess (source ,[{markup : () => {console .log ('markup-1');},script : () => {console .log ('script-1');},style : () => {console .log ('style-1');}},{markup : () => {console .log ('markup-2');},script : () => {console .log ('script-2');},style : () => {console .log ('style-2');}}],{filename : 'App.svelte'});// Svelte 3 logs:// markup-1// markup-2// script-1// script-2// style-1// style-2// Svelte 4 logs:// markup-1// script-1// style-1// markup-2// script-2// style-2
Ceci peut vous affecter si vous utilisez par exemple MDsveX
- pour lequel vous devez vous assurer qu'il vient avant n'importe quel préprocesseur de script ou de style :
preprocess: [
vitePreprocess(),
mdsvex(mdsvexConfig)
mdsvex(mdsvexConfig),
vitePreprocess()
]
Chaque préprocesseur doit également avoir un nom. (#8618)
Nouvelle librairie eslintpermalink
eslint-plugin-svelte3
est déprécié. Il est possible qu'il fonctionne encore avec Svelte 4, mais nous ne le garantissons pas. Nous recommandons de passer à notre nouvelle librairie [eslint-plugin-svelte] (https://github.com/sveltejs/eslint-plugin-svelte). Voir ce ticket Github pour des instructions sur la façon de migrer. Alternativement, vous pouvez créer un nouveau projet en utilisant npm create svelte@latest
, sélectionner l'option eslint (et éventuellement TypeScript) et ensuite copier les fichiers associés dans votre projet existant.
Autres changements majeurspermalink
- l'attribut
inert
est maintenant appliqué aux éléments sortants pour les rendre invisibles aux technologies d'assistance et empêcher l'interaction. (#8628) - le runtime utilise maintenant
classList.toggle(name, boolean)
qui peut ne pas fonctionner dans les très vieux navigateurs. Envisagez d'utiliser un polyfill si vous avez besoin de supporter ces navigateurs. (#8629) - le runtime utilise maintenant le constructeur
CustomEvent
qui peut ne pas fonctionner dans les très vieux navigateurs. Envisagez d'utiliser un [polyfill] (https://github.com/theftprevention/event-constructor-polyfill/tree/master) si vous avez besoin de supporter ces navigateurs. (#8775) - Les personnes qui implémentent leurs propres stores en utilisant l'interface
StartStopNotifier
(qui est passée à la fonction create dewritable
etc) desvelte/store
doivent maintenant passer une fonction de mise à jour en plus de la fonction set. Cela n'a aucun effet sur les personnes qui utilisent des stores ou qui créent des stores en utilisant les stores Svelte existants. (#6750) derived
lancera maintenant une erreur sur les valeurs falsy au lieu des stores qui lui sont passés. (#7947)- les définitions de type pour
svelte/internal
ont été supprimées pour décourager encore plus l'utilisation de ces méthodes internes qui ne sont pas des API publiques. La plupart de ces éléments seront probablement modifiés pour Svelte 5. - La suppression des noeuds du DOM se fait maintenant par lots, ce qui modifie légèrement l'ordre, ce qui peut affecter l'ordre des événements déclenchés si vous utilisez un
MutationObserver
sur ces éléments (#8763) - si vous avez étendu les typages globaux à travers le namespace
svelte.JSX
auparavant, vous devez les migrer pour utiliser le namespacesvelteHTML
. De même, si vous avez utilisé le namespacesvelte.JSX
pour utiliser des définitions de types, vous devez les migrer pour utiliser les types desvelte/elements
à la place. Vous pouvez trouver plus d'informations sur ce qu'il faut faire ici