Skip to main content

Bonnes pratiques

Ce document met en lumière certaines bonnes pratiques qui vous aideront à écrire des applications Svelte rapides et robustes. Il est également disponible en tant que skill svelte-core-bestpractices pour vos agents.

$state

Utilisez uniquement la rune $state pour des variables qui ont besoin d'être réactives — en d'autres mots, pour des variables qui peuvent provoquer la mise à jour d'un $effect, d'un $derived ou d'expressions de templates. Tout le reste peut être une variable normale.

Les tableaux et les objets ($state({...}) ou $state([...])) sont rendus profondément réactifs, ce qui signifie que leur mutation va déclencher des mises à jour. Ceci a une contrepartie : en échange d'une réactivité fine, les objets doivent être transformés en proxies, ce qui implique un surcoût en performances. Dans les cas où vous travaillez sur de gros objets qui ne sont que réassignés (plutôt que mutés), utilisez plutôt $state.raw. C'est souvent le cas avec les réponses d'API, par exemple.

$derived

Pour calculer quelque chose depuis un état, utilisez $derived plutôt que $effect :

// faites ceci
let square = 
function $derived<number>(expression: number): number
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}
@paramexpression The derived state expression
$derived
(let num: numbernum * let num: numbernum);
// ne faites pas ceci let square;
function $effect(fn: () => void | (() => void)): void
namespace $effect

Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values. The timing of the execution is after the DOM has been updated.

Example:

$effect(() => console.log('The count is now ' + count));

If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.

Does not run during server-side rendering.

@see{@link https://svelte.dev/docs/svelte/$effect Documentation}
@paramfn The function to execute
$effect
(() => {
let square: numbersquare = let num: numbernum * let num: numbernum; });

On fournit à $derived une expression, et pas une fonction. Si vous devez utiliser une fonction (car l'expression est complexe, par exemple), utilisez $derived.by.

Les dérivées sont modifiables — vous pouvez leur assigner des valeurs, comme avec $state, mais elles seront ré-évaluées lorsque leur expression sera mise mise à jour.

Si l'expression dérivée est un objet ou un tableau, celui-ci sera renvoyé tel quel — il ne sera pas rendu profondément réactif. Vous pouvez toutefois utilisez $state dans $derived.by dans les rares cas où vous en auriez besoin.

$effect

Les effets sont un outil de dernier recours et devraient être évités si possible. En particulier, évitez de mettre à jour un état dans un effet.

  • Si vous avez besoin de vous synchroniser avec une librairie externe comme D3, il est souvent plus simple d'utiliser {@attach ...}
  • Si vous avez besoin d'exécuter du code en réponse à une interaction utilisateur, mettez le code directement dans un gestionnaire d'évènement ou utilisez une liaison de fonction, selon ce qui est le plus approprié
  • Si vous avez besoin de logguer des valeurs pour déboguer, utiliser $inspect
  • Si vous avez besoin d'observer quelque chose d'externe à Svelte, utilisez createSubscriber

N'entourez jamais le contenu d'un effet avec if (browser) {...} ou similaire — les effets ne sont jamais exécutés sur le serveur.

$props

Traitez les props comme si elles ne changeaient jamais. Par exemple, les valeurs qui dépendent de props devraient en général être des $derived :

let { let type: anytype } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
@see{@link https://svelte.dev/docs/svelte/$props Documentation}
$props
();
// faites ceci let color =
function $derived<"red" | "green">(expression: "red" | "green"): "red" | "green"
namespace $derived

Declares derived state, i.e. one that depends on other state variables. The expression inside $derived(...) should be free of side-effects.

Example:

let double = $derived(count * 2);
@see{@link https://svelte.dev/docs/svelte/$derived Documentation}
@paramexpression The derived state expression
$derived
(let type: anytype === 'danger' ? 'red' : 'green');
// ne faites pas ceci — `color` ne sera jamais mise à jour si `type` change let color = let type: anytype === 'danger' ? 'red' : 'green';

$inspect.trace

$inspect.trace est un outil de déboguage pour la réactivité. Si quelque chose ne se met pas correctement à jour ou est exécuté plus souvent que nécessaire, vous pouvez ajouter $inspect.trace(label) en tant que première ligne d'un $effect ou d'un $derived.by (ou de n'importe quelle fonction appelée par l'un d'eux) pour tracer leurs dépendances et trouver lequel déclenche une mise à jour.

Évènements

Tout attribut d'élément commençant par on est traité comme un gestionnaire d'évènement :

<button onclick={() => {...}}>click me</button>

<!-- les raccourcis d'attributs fonctionnent également -->
<button {onclick}>...</button>

<!-- ainsi que le spread d'attribut -->
<button {...props}>...</button>

Si vous avez besoin d'attacher des gestionnaires à window ou document vous pouvez utiliser <svelte:window> et <svelte:document> :

<svelte:window onkeydown={...} />
<svelte:document onvisibilitychange={...} />

Évitez d'utiliser onMount ou $effect pour faire cela.

Snippets

Snippets sont une manière de définir des morceaux de markup réutilisables pouvant être instanciés avec la balise {@render ...}, ou passés en tant que props de composants. Ils doivent être déclarés au sein du template.

{#snippet greeting(name)}
  <p>bonjour {name} !</p>
{/snippet}

{@render greeting('tout le monde')}

Les snippets déclarés à la racine d'un composant (c-à-d pas dans des éléments ou des blocs) peuvent être référencés au sein d'un <script>. Un snippet qui ne référence pas un état de composant est également disponible dans <script module>, et peut ainsi être exporté pour être utilisé par d'autres composants.

Blocs each

Privilégiez l'usage de blocs each à clé — ceci améliore les performances en permettant à Svelte d'insérer ou de supprimer des éléments chirurgicalement plutôt que de mettre à jour le DOM d'éléments déjà existants.

La clé doit identifier de manière unique l'objet. N'utilisez pas l'indice de boucle comme clé.

Évitez de déstructurer si vous avez besoin de muter l'élément (avec quelque chose comme bind:value={item.count} par exemple).

Utiliser des variables Javascript dans le CSS

Si vous avez une variable JS que vous souhaitez utiliser dans votre CSS, vous pouvez définir une propriété CSS personnalisée avec la directive style:.

<div style:--columns={columns}>...</div>

Vous pouvez alors référencer var(--columns) dans la balise <style> du composant.

Styliser les composants enfant

Le CSS de la balise <style> d'un composant est scopé à ce composant. Si un composant parent a besoin de contrôler les styles d'un enfant, la manière recommandée est d'utiliser des propriétés CSS personnalisées :

<!-- Parent.svelte -->
<Child --color="red" />

<!-- Child.svelte -->
<h1>Bonjour</h1>

<style>
	h1 {
		color: var(--color);
	}
</style>

Si ceci n'est pas possible (par exemple, le composant enfant vient d'une librairie), vous pouvez utiliser :global pour écraser les styles :

<div>
	<Child />
</div>

<style>
	div :global {
		h1 {
			color: red;
		}
	}
</style>

Contexte

Envisagez l'usage du contexte plutôt que de déclarer un état dans un module partagé. Ceci va scoper l'état à la partie de l'application qui en a besoin, et éliminer la possibilité que celui "fuite" entre les utilisateurs lors du rendu côté serveur.

Utilisez createContext plutôt que setContext et getContext, car cette méthode fournit du typage.

Svelte asynchrone

Si vous utilisez la version 5.36 ou supérieur, vous pouvez utiliser les expressions await et les hydratables pour utiliser les promesses directement dans vos composants. Notez que ces expressions nécessitent d'avoir activé l'option experimental.async dans le fichier de configuration svelte.config.js, car elles ne sont pas encore considérées comme parfaitement stables.

Évitez l'usage de fonctionnalités dépréciées

Utilisez systématiquement le mode runes pour du nouveau code, et évitez les fonctionnalités qui ont un équivalent plus moderne :

  • utilisez $state plutôt que la réactivité implicite (par ex. let count = 0; count += 1)
  • utilisez $derived et $effect plutôt que les assignations et déclarations $: (mais n'utilisez les effets que lorsqu'il n'y a pas de meilleure solution)
  • utilisez $props plutôt que export let, $$props et $$restProps
  • utilisez onclick={...} plutôt que on:click={...}
  • utilisez {#snippet ...} et {@render ...} plutôt que <slot>, $$slots et <svelte:fragment>
  • utilisez <DynamicComponent> plutôt que <svelte:component this={DynamicComponent}>
  • utilisez import Self from './ThisComponent.svelte' et <Self> plutôt que <svelte:self>
  • utilisez les classes avec des champs $state pour partager des comportements réactifs entre composants plutôt qu'utiliser des stores
  • utilisez {@attach ...} plutôt que use:action
  • utilsez les tableaux et objets à la manière de clsx dans les attributs class plutôt que la directive class:

Modifier cette page sur Github llms.txt

précédent suivant