Bonnes pratiques pour travailler avec Svelte
Si vous avez dépassé les bases de Svelte et commencé à développer de vraies applications, vous avez probablement remarqué que la documentation officielle couvre ce que font les choses, mais pas toujours quand ni pourquoi les utiliser. Cet article se concentre sur les bonnes pratiques de Svelte 5 qui améliorent la maintenabilité, les performances et la clarté du code en production, en supposant que vous comprenez déjà le fonctionnement des composants et de la réactivité.
Points clés à retenir
- Utilisez
$stateuniquement lorsqu’une valeur déclenche des mises à jour de l’interface, et privilégiez$state.rawlorsque vous remplacez des valeurs plutôt que de les muter. - Préférez
$derivedà$effectpour les valeurs calculées ; réservez$effectà la synchronisation avec des systèmes externes. - Évitez l’état au niveau du module dans les environnements SSR. Utilisez l’API de contexte de Svelte avec
$statebasé sur des classes pour un état partagé typé et limité à la portée de la requête. - Dans SvelteKit, utilisez
+page.server.jspour les données côté serveur des pages et+server.jspour les endpoints API autonomes. - Adoptez la syntaxe moderne de Svelte 5 (
onclick,{#snippet},$props()) plutôt que les anciens modèles dans le nouveau code.
Les runes de Svelte 5 : utilisez-les avec précision
Les runes de Svelte 5 constituent le modèle principal de réactivité, et les utiliser correctement importe davantage que de les utiliser partout.
N’employez $state que lorsqu’une variable doit déclencher des mises à jour de l’interface. Les variables simples sont moins coûteuses et plus claires pour tout le reste.
Lorsque votre état est un objet ou un tableau volumineux qui est remplacé plutôt que muté, utilisez plutôt $state.raw :
// ❌ Surcharge de proxy inutile pour des données d'API que vous ne ferez que réassigner
let users = $state(await fetchUsers());
// ✅ Aucun coût de proxy lorsque vous remplacez plutôt que mutez
let users = $state.raw(await fetchUsers());
Utilisez $state lorsque vous devez muter directement des propriétés imbriquées (comme cart.items[0].quantity++). Utilisez $state.raw lorsque vous remplacez la valeur entière.
Préférez $derived à $effect pour les valeurs calculées
C’est l’une des erreurs les plus courantes dans le développement moderne avec Svelte :
let num = $state(0);
// ❌ À éviter — crée un effet de bord inutile
let square = $state(0);
$effect(() => { square = num * num; });
// ✅ Correct — déclaratif et avec suivi des dépendances
let square = $derived(num * num);
$effect est une issue de secours. Réservez-le à la synchronisation avec des systèmes externes (comme D3), et envisagez {@attach} pour les intégrations au niveau du DOM lorsque cela convient naturellement.
Traitez les props comme dynamiques
Les valeurs dérivées des props doivent utiliser $derived, et non une simple affectation :
let { type } = $props();
// ✅ Reste synchronisé lorsque `type` change
let color = $derived(type === 'danger' ? 'red' : 'green');
Discover how at OpenReplay.com.
Un contexte typé plutôt que des modules partagés
Pour un état partagé au sein d’un sous-arbre de composants, privilégiez l’API de contexte de Svelte plutôt qu’un état au niveau du module. L’état au niveau du module persiste entre les requêtes dans les environnements SSR, ce qui peut entraîner des fuites de données entre utilisateurs.
Le modèle moderne utilise une classe avec des champs $state :
// lib/theme.svelte.ts
import { getContext, setContext } from 'svelte';
class ThemeContext {
current = $state('light');
toggle() {
this.current = this.current === 'light' ? 'dark' : 'light';
}
}
const KEY = Symbol('theme');
export const setTheme = () => setContext(KEY, new ThemeContext());
export const getTheme = () => getContext<ThemeContext>(KEY);
Cela vous offre la sécurité des types, un état réactif et une portée SSR correcte en un seul modèle.
Chargement des données dans SvelteKit : choisir le bon modèle
Une source fréquente de confusion dans SvelteKit est de savoir quand utiliser +page.server.js plutôt que +server.js :
| Scénario | À utiliser |
|---|---|
| Récupérer des données pour une page avec SSR ou accès serveur uniquement | +page.server.js avec load() |
| Construire un endpoint d’API destiné à un usage externe | +server.js |
| Données côté client uniquement après l’hydratation | onMount + fetch |
Pour les données de page nécessitant un accès serveur, des secrets ou le SSR, +page.server.js est généralement le choix par défaut le plus pertinent. Il s’exécute côté serveur, garde les secrets hors du client et s’intègre proprement aux form actions de SvelteKit pour l’amélioration progressive.
Petites victoires pratiques
Les blocs {#each} avec clé préviennent les bugs subtils de recyclage du DOM. Indexez toujours par un identifiant unique stable, jamais par l’index.
$inspect.trace est sous-utilisé pour déboguer la réactivité. Placez-le en haut de n’importe quel $effect ou $derived.by pour voir exactement quelle dépendance a déclenché une nouvelle exécution.
Les snippets plutôt que les slots pour les blocs de balisage réutilisables. Les snippets se composent mieux et peuvent être passés en tant que props, rendant les API de composants plus propres.
Évitez la syntaxe héritée dans le nouveau code. Remplacez on:click par onclick, <slot> par {#snippet}, et export let par $props(). Ces modèles s’alignent sur les conventions modernes de Svelte 5 et sur le comportement actuel du compilateur.
Conclusion
Svelte 5 récompense la retenue. Plus vous délimitez précisément la réactivité — en utilisant $state uniquement là où c’est nécessaire, $derived plutôt que $effect, et le contexte plutôt que des variables globales de module — plus votre application devient prévisible et performante. Commencez par la primitive réactive la plus simple qui résout le problème, et ne recourez à des outils plus puissants que lorsque les plus simples se révèlent réellement insuffisants.
FAQ
Utilisez $state.raw lorsque vous prévoyez de remplacer la valeur entière plutôt que d'en muter certaines parties, par exemple lors du stockage de réponses d'API récupérées ou de grands tableaux que vous réassignez en bloc. Cela évite la surcharge du proxy réactif, ce qui améliore les performances pour les grands ensembles de données. Utilisez $state simple lorsque vous avez besoin d'une réactivité fine pour des mutations imbriquées, comme la mise à jour d'un élément à l'intérieur d'un tableau.
$derived est déclaratif, suit automatiquement ses dépendances et produit une valeur en lecture seule qui reste synchronisée. $effect s'exécute de manière impérative comme un effet de bord et est plus difficile à appréhender, car il peut introduire des bugs de timing et des réexécutions inutiles. Réservez $effect à la synchronisation avec des systèmes en dehors de la réactivité de Svelte, comme des bibliothèques tierces, des API canvas ou des manipulations manuelles du DOM.
Pas dans les environnements SSR comme SvelteKit. L'état au niveau du module est partagé entre toutes les requêtes traitées par le serveur, ce qui peut faire fuiter les données d'un utilisateur dans la session d'un autre. Utilisez l'API de contexte de Svelte avec setContext et getContext, idéalement adossée à une classe contenant des champs $state. Cela limite la portée de l'état à chaque requête et à chaque arbre de composants tout en préservant la réactivité et la sécurité des types.
Utilisez +page.server.js lorsque les données appartiennent à une page spécifique et bénéficient du SSR, du SEO, d'un accès côté serveur ou des form actions. Utilisez +server.js lorsque vous avez besoin d'un endpoint HTTP autonome, comme une API JSON consommée par des clients externes, des webhooks ou des appels fetch non liés à une page. Si les données ne sont rendues que par une seule page et nécessitent des capacités côté serveur, +page.server.js est généralement le meilleur choix par défaut.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.