Svelte 5 Statique Uniquement (Runes)
Ce que couvre cette compétence
« Statique uniquement » signifie que le livrable est un dossier de fichiers HTML/CSS/JS pré-générés, sans serveur Node.js/Edge à l'exécution — il peut être hébergé sur GitHub Pages, Netlify/Cloudflare/Vercel statique, S3+CloudFront, ou ouvert comme fichiers locaux. Cette contrainte exclut +page.server.js, +server.js, les actions de formulaire, hooks.server.js, et tout chemin de code qui suppose un serveur en cours d'exécution. « Runes » signifie que la réactivité des composants est écrite avec les primitives Svelte 5 $state/$derived/$effect/$props, et non avec export let / $: / la réactivité implicite de Svelte 4.
Ces deux contraintes interagissent : une construction statique ne fonctionne proprement que si aucun code — y compris à l'intérieur de $effect — ne suppose qu'il s'exécute sur un serveur par requête. Gardez cela à l'esprit tout au long du processus ; c'est la source de la plupart des bogues lorsque les gens migrent une application SvelteKit vers adapter-static.
Étape 1 — Choisir la forme de projet appropriée
Demandez (ou déduisez du contexte) si l'application a besoin d'un routage basé sur les fichiers, de plusieurs pages pré-rendues, ou d'un HTML SEO-friendly par route. Cela détermine toute la configuration, donc ne sautez pas cette étape.
| Besoin | Utilisation |
|---|---|
| Page unique / tableau de bord / widget / intégration, pas de routage | Vite + Svelte simple (npm create vite@latest -- --template svelte-ts). Configuration statique la plus simple possible — il n'y a aucun serveur à introduire accidentellement. |
| Plusieurs routes, chacune pré-rendue dans son propre fichier HTML, SEO important | SvelteKit + @sveltejs/adapter-static avec prerender = true. |
| Plusieurs routes, mais SEO sans importance (outil interne, extension Chrome, UI Electron/Tauri) | SvelteKit + adapter-static en mode SPA (un seul shell fallback: 'index.html', routage côté client). |
Optez par défaut pour Vite + Svelte simple sauf si un routage est spécifiquement nécessaire — cela comporte moins de risques de mauvaise configuration. Les étapes complètes de configuration, les fichiers de configuration et les notes de déploiement pour les deux chemins se trouvent dans references/static-build.md ; lisez-le avant de générer svelte.config.js / vite.config.js de mémoire, car les options de pré-rendu/d'adaptateur changent entre les versions de Svelte et il est facile de se tromper subtilement (par exemple, oublier trailingSlash, ou définir ssr = false sur une page que vous souhaitez également pré-rendre, ce qui produit une coquille vide au lieu d'un vrai HTML).
Étape 2 — Écrire les composants avec des runes, pas la syntaxe Svelte 4
N'écrivez jamais export let, $:, on:click, ou un store writable() nu comme moyen principal de gérer l'état des composants dans du nouveau code Svelte 5 — ces éléments se compilent encore dans la plupart des configurations mais ce sont des motifs hérités ; la question ici porte spécifiquement sur les runes. La correspondance de base :
| Svelte 4 | Svelte 5 |
|---|---|
let count = 0 (réactif car au niveau supérieur) | let count = $state(0) |
$: doubled = count * 2 | let doubled = $derived(count * 2) (ou $derived.by(() => ...) pour une logique multi-instructions) |
$: { sideEffect(count) } | $effect(() => { sideEffect(count) }) |
export let name | let { name } = $props() |
export let value; bind:value (l'enfant mute) | let { value = $bindable() } = $props() |
onMount/onDestroy pour la configuration/démontage DOM uniquement | $effect(() => { ...; return () => cleanup(); }) |
<slot name="header"> | {#snippet header()}...{/snippet} + {@render header()} |
store writable()/readable(), $store dans les composants | $state(...) dans un module .svelte.js/.svelte.ts, importé directement (la réactivité fonctionne désormais en dehors des composants) |
Lisez references/runes.md avant d'écrire du code non trivial avec des runes — cela couvre les parties que les gens comprennent mal de manière fiable : $derived doit rester pur (pas d'effets de bord, pas de mutation d'état à l'intérieur), $effect ne doit jamais écrire dans le même état qu'il lit (boucle infinie), $state.raw pour les données volumineuses/gelées que vous réaffectez plutôt que de muter, $effect.root/untrack pour l'état partagé en dehors des cycles de vie des composants, et le modèle exact basé sur les classes pour l'état inter-composants/modules. Se tromper sur ces points produit des bogues qui ne se manifestent que sous forme de boucles de rendu étranges ou d'interface utilisateur obsolète, difficiles à diagnostiquer après coup — il est préférable de les écrire correctement du premier coup.
Lors de la migration de code Svelte 4 existant, npx sv migrate svelte-5 gère la réécriture mécanique (c'est l'outil actuel ; les anciennes documentations peuvent référencer svelte-migrate), mais examinez toujours le diff — la migration automatisée ne corrige pas de manière fiable les motifs de stores comme état inter-modules ou les effets qui auraient dû être des valeurs dérivées.
Étape 3 — Appliquer la checklist de sécurité
L'hébergement statique ne signifie pas « aucune surface de sécurité » — cela supprime les vecteurs d'attaque côté serveur mais les vecteurs côté client (XSS, fuite de secrets, intégrations tierces dangereuses) sont entièrement de votre responsabilité puisqu'il n'y a pas de couche serveur pour les rattraper. Avant de terminer toute tâche qui touche au contenu généré par l'utilisateur, à {@html}, aux variables d'environnement, ou aux scripts tiers, consultez references/security.md. Les règles à plus fort impact, pour qu'elles ne soient pas oubliées même lors d'une tâche rapide :
- Ne passez jamais de contenu non nettoyé à
{@html}. Svelte échappe automatiquement tout dans les accolades{expression}, mais{@html ...}contourne complètement cela — c'est la plus grande source de XSS dans les applications Svelte. Nettoyez avec DOMPurify (ou une liste blanche stricte) immédiatement avant le rendu, et non plus tôt dans le pipeline où cela pourrait être contourné par une modification ultérieure. - Ne mettez jamais un vrai secret derrière une variable d'environnement préfixée par
VITE_(ou parPUBLIC_dans SvelteKit). Vite intègre ces variables dans le bundle JS livré au moment de la construction — n'importe qui peut les lire à partir des fichiers construits. Une application statique n'a aucun serveur pour cacher un secret, donc si l'application a besoin d'une vraie clé API, la clé appartient au serveur du service tiers ou derrière une fonction serverless/proxy séparé que je déploie ailleurs — signalez-le-moi plutôt que de câbler silencieusement la clé dans le code client. - Définissez une Content-Security-Policy même s'il n'y a pas de serveur pour envoyer les en-têtes. Les hébergeurs statiques prennent en charge cela via une balise
<meta http-equiv="Content-Security-Policy">dansapp.html/index.html, ou via un fichier d'en-têtes spécifique à l'hébergeur (Netlify_headers, Cloudflare Pages_headers, en-têtes Vercelvercel.json) — voirreferences/security.mdpour les deux. - Considérez chaque
href/srcdynamique comme contrôlé par un attaquant s'il peut provenir d'une saisie utilisateur ou d'une réponse d'API. Svelte ne bloque pas les URLsjavascript:dans les liaisonshref— validez/filtrez le protocole vous-même. - Exécutez
npm audit(ou équivalent) et verrouillez les lockfiles avant de livrer — les sites statiques livrent toujours le code de chaque dépendance directement au navigateur, donc une dépendance compromise est une compromission directe du côté client.
Fichiers de référence
references/runes.md— guide rune par rune complet avec modèles corrects/incorrects, état partagé basé sur les classes, typage TypeScript pour les props/snippets, et le tableau de migration Svelte 4 vers 5 en détail.references/static-build.md— configuration Vite + Svelte simple, configuration SvelteKit + adapter-static (modes pré-rendu complet et fallback SPA), pièges trailing-slash/base-path, et notes de déploiement par hébergeur (GitHub Pages, Netlify, Cloudflare Pages, S3/CloudFront).references/security.md— checklist complète : XSS/{@html}/DOMPurify, CSP pour les hébergeurs statiques (balise meta + modèles_headers), secrets/variables d'environnement, liens externes sécurisés, audit des dépendances, Trusted Types, sensibilité de localStorage/sessionStorage, et une checklist pré-livraison.assets/— fichiers de démarrage copiables :vite.config.ts,svelte.config.js(adapter-static),_headers(modèle CSP), etSecureHtml.svelte(un composant wrapper DOMPurify).
Utilisez ces fichiers selon vos besoins plutôt que de reproduire leur contenu de mémoire — les noms d'options de configuration et les spécificités des directives CSP sont exactement le genre de détail qui devient obsolète ou mal retenu.