Svelte 5: De compilergestuurde aanpak en het mentale model
Stel je een JavaScript-framework voor dat tijdens de bouw volledig verdwijnt. Geen bibliotheken om te downloaden, nee virtuele DOM moet tijdens runtime worden afgestemd, geen raamwerkoverhead zichtbaar in browserinspecteur. Dit en Svelte: geen raamwerk in de traditionele zin van het woord, maar a compiler die .svelte-componenten transformeert in puur en geoptimaliseerd JavaScript. Svelte 5, uitgebracht in oktober 2024, brengt dit model naar een ga een level omhoog met Runes, een universeel, op signalen gebaseerd reactiviteitssysteem dat een revolutie in de wereld heeft teweeggebracht waar u de status in applicaties beheert.
Als je uit React, Vue of Angular komt, vereist het mentale model van Svelte een verandering van perspectief. Het gaat er niet om om een nieuwe API te leren, maar om te begrijpen dat het raamwerk zelf niet bestaat tijdens runtime. Deze gids helpt je om dat mentale model te bouwen, door te onderzoeken hoe de Svelte-compiler intern werkt en waarom Runes vertegenwoordigen de natuurlijke evolutie van deze aanpak.
Wat je gaat leren
- Hoe de Svelte-compiler componenten omzet in puur JavaScript
- Omdat Svelte geen virtuele DOM nodig heeft
- Het juiste mentale model voor het werken met Svelte 5
- Inleiding tot Runen en signaalgebaseerde reactiviteit
- Prestatievergelijking met React en Vue (gegevens 2025-2026)
- Hoe je de eerste Svelte 5-component met Runen maakt
Het probleem met virtuele DOM's
Om te begrijpen waarom Svelte bestaat, moet je eerst begrijpen wat het oplost. React, Vue en Angular gebruiken allemaal a virtuele DOM: een representatie in het geheugen van de daadwerkelijke DOM die het raamwerk gebruikt om te berekenen de verschillen (verschillen) en pas alleen de noodzakelijke wijzigingen toe. Deze aanpak is intuïtief zinvol – en Het is efficiënter om een representatie in het geheugen bij te werken dan om de DOM rechtstreeks te manipuleren, maar er zijn kosten aan verbonden verborgen: virtuele DOM-afstemming vindt altijd plaats, zelfs als er niets is veranderd.
Rich Harris, de maker van Svelte, bedacht de term "virtuele DOM is pure overhead" binnen een artikel uit 2019 dat aanleiding gaf tot een levendig debat in de gemeenschap. Het punt is niet dat de virtuele DOM is over het algemeen traag, maar introduceert onnodig werk dat de compiler zou kunnen elimineren.
Overweeg een React-component die een teller weergeeft:
// React: il virtual DOM riconcilia ad ogni render
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Contatore: {count}</p>
<button onClick={() => setCount(count + 1)}>
Incrementa
</button>
</div>
);
}
Elke keer dat de status verandert, moet React: Een nieuwe virtuele DOM voor de component maken en deze vergelijken de vorige (verschillend), bepaal wat er is veranderd en werk ten slotte de echte DOM bij. De compiler Svelte weet tijdens het bouwen al wat er kan veranderen (alleen de tekst van de alinea) en genereert deze direct code om het bij te werken, zonder tussenstappen.
Hoe de Svelte Compiler werkt
Een slanke component en een .svelte die drie optionele secties bevat: script, sjabloon en
stijlen. Tijdens de build ontleedt de compiler dit bestand en genereert JavaScript dat het
DOM, met gedetailleerde en chirurgische updates.
<!-- Counter.svelte - Il componente sorgente -->
<script>
let count = $state(0);
</script>
<p>Contatore: {count}</p>
<button onclick={() => count++}>
Incrementa
</button>
De compiler analyseert het sjabloon en begrijpt dat {count} en het enige deel dat verandert.
Het gegenereerde JavaScript bevat direct: Maak het knooppunt <p>, voeg een tekstknooppunt in,
en registreer een effect dat dat tekstknooppunt alleen bijwerkt wanneer count wijziging. Geen virtuele DOM,
geen meningsverschil, geen verzoening.
De gecompileerde code ziet er, vereenvoudigd, als volgt uit:
// Output del compilatore Svelte (semplificato)
import { mount, text, element } from 'svelte/internal';
export function Counter(target) {
let count = 0;
const p = element('p');
const countText = text(`Contatore: ${count}`);
const button = element('button');
button.addEventListener('click', () => {
count++;
// Aggiorna SOLO il text node specifico
set_data(countText, `Contatore: ${count}`);
});
append(p, countText);
append(target, p);
append(target, button);
}
Dit is de kern van de compilergestuurde aanpak: de compiler weet precies wat hij kan veranderen en genereren optimale code om dit af te handelen, in plaats van dit werk tijdens runtime te delegeren aan een generiek diffing-algoritme.
Vergelijking bundelgrootte (2025)
Een gelijkwaardige TodoList-component produceert JavaScript-bundels van zeer verschillende groottes in de belangrijkste raamwerken:
- Reageer 19 + ReactDOM: ~42 KB gzipt (runtime inbegrepen)
- Vue 3.5: ~22 KB gzipt (runtime inbegrepen)
- Hoekig 19 (standalone): ~35 KB gzipt (runtime inbegrepen)
- Snel 5: ~2-5 KB gzipt (geen runtime, alleen de component)
Voor grote toepassingen met veel componenten wordt het voordeel kleiner omdat elk Svelte-component is inbegrepen de updatecode. Maar voor middelgrote toepassingen blijft Svelte de overall winnaar in termen van payload naar de browser.
De paradigmaverschuiving van Svelte 5: The Runes
Svelte 4 gebruikte een magisch reactiviteitssysteem op basis van opdrachten: elke variabele in het blok
<script> het was automatisch reactief en de compiler volgde de afhankelijkheden overal
de bouw. Dit werkte goed voor eenvoudige gevallen, maar had belangrijke beperkingen: reactiviteit werkte
alleen binnen .svelte-componenten, en het magische gedrag maakte het moeilijk om over de code te redeneren.
Svelte 5 introduceert i Runen: speciale functies met het voorvoegsel $ die communiceren
rechtstreeks met de compiler. Runen zijn geen normale functies — $state() het is geen functie
dat importeert en aanroept - maar speciale syntaxis herkend door de compiler, vergelijkbaar met hoe useState()
in React wordt het door de transpiler herkend voor lint- en typecontroles, maar het is eigenlijk een gewone functie.
Het belangrijkste verschil: Runen werken overal, niet alleen in .svelte-bestanden:
// counter.svelte.ts - Un modulo TypeScript puro con reattivita Svelte 5
export function createCounter(initial: number = 0) {
let count = $state(initial);
// $derived calcola automaticamente quando count cambia
const doubled = $derived(count * 2);
const isEven = $derived(count % 2 === 0);
function increment() { count++; }
function decrement() { count--; }
function reset() { count = initial; }
return {
get count() { return count; },
get doubled() { return doubled; },
get isEven() { return isEven; },
increment,
decrement,
reset
};
}
// Usabile in qualsiasi componente .svelte
// o in altri file TypeScript che importano questo modulo
Dit is een radicale verandering vergeleken met Svelte 4: de bedrijfslogica met zijn reactiviteit kan blijven bestaan in afzonderlijke TypeScript-modules, deelbaar tussen componenten, afzonderlijk testbaar met normale unit-tests, zonder afhankelijkheden van een renderingomgeving.
De vier fundamentele runen
Svelte 5 introduceert vier hoofdrunen die de meeste gebruiksscenario's dekken:
<script lang="ts">
// $state: stato reattivo (sostituisce let reattivo di Svelte 4)
let name = $state('Federico');
let items = $state<string[]>([]);
// $derived: valori computati (sostituisce $: di Svelte 4)
const greeting = $derived(`Ciao, ${name}!`);
const itemCount = $derived(items.length);
// $effect: side effects (sostituisce $: con side effects di Svelte 4)
$effect(() => {
console.log('name cambiato:', name);
// Cleanup automatico quando l'effetto si ri-esegue
return () => console.log('cleanup prima del prossimo run');
});
// $props: props del componente (sostituisce export let di Svelte 4)
const { title, onClose = () => {} } = $props<{
title: string;
onClose?: () => void;
}>();
</script>
Svelte 4 versus Svelte 5: belangrijkste verschillen
Als je ervaring hebt met Svelte 4, veranderen de Runen de syntaxis aanzienlijk:
- Snel 4:
let count = 0;(impliciete magie) → Snel 5:let count = $state(0);(expliciet) - Snel 4:
$: doubled = count * 2;→ Snel 5:const doubled = $derived(count * 2); - Snel 4:
export let prop;→ Snel 5:const { prop } = $props(); - Snel 4:
on:click={handler}→ Snel 5:onclick={handler}
Svelte 5 onderhoudt achterwaartse compatibiliteit met Svelte 4 in "legacy-modus", zodat de migratie geleidelijk kan plaatsvinden.
Svelte 5 versus React: een praktische vergelijking
Om het verschil in aanpak concreet te begrijpen, laten we hetzelfde onderdeel bekijken dat is geïmplementeerd in React en Svelte 5:
// React 19: SearchBox con debounce
import { useState, useEffect, useCallback } from 'react';
function SearchBox({ onSearch }: { onSearch: (q: string) => void }) {
const [query, setQuery] = useState('');
const [debouncedQuery, setDebouncedQuery] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedQuery(query);
}, 300);
return () => clearTimeout(timer);
}, [query]);
useEffect(() => {
if (debouncedQuery) onSearch(debouncedQuery);
}, [debouncedQuery, onSearch]);
return (
<input
value={query}
onChange={e => setQuery(e.target.value)}
placeholder="Cerca..."
/>
);
}
<!-- Svelte 5: SearchBox con debounce -->
<script lang="ts">
const { onSearch }: { onSearch: (q: string) => void } = $props();
let query = $state('');
$effect(() => {
const timer = setTimeout(() => {
if (query) onSearch(query);
}, 300);
return () => clearTimeout(timer);
});
</script>
<input bind:value={query} placeholder="Cerca..." />
De Svelte 5-versie is beknopter, niet omdat het "magisch" is: het is omdat de compiler de synchronisatie beheert
tussen query en invoer via bind:value, En $effect automatisch volgen
afhankelijkheid van query zonder dat u dit expliciet hoeft te declareren in de afhankelijkheidsarray.
Echte prestaties: gegevens en benchmarks
Synthetische benchmarks zijn vaak misleidend, maar de gegevens van JS Framework-benchmark 2025 (draait op echte hardware met intensieve DOM-bewerkingen) laat Svelte 5 consistent in het bovenste kwartiel zien voor bijna alle geteste operaties:
- 10.000 rijen maken: Svelte 5 ~1,2x overhead versus Vanilla JS, Reageer ~2,1x
- Update elke 10e rij: Slank 5 ~1,1x, reageren ~1,8x
- Rijmarkering selecteren: Slank 5 ~1,05x, Reageer ~1,4x
- Geheugen na creatie: Svelte 5 gebruikt ~40% minder geheugen dan React
Het voordeel is het meest uitgesproken op goedkope mobiele apparaten, waar JavaScript wordt geparseerd en uitgevoerd ze kosten meer. Op moderne desktops is het praktische verschil voor typische toepassingen vaak onzichtbaar naar de eindgebruiker.
Het eerste snelle project maken 5
De snelste manier om aan de slag te gaan met Svelte 5 is door SvelteKit te gebruiken, het officiële full-stack framework gebaseerd op Svelte:
# Crea un nuovo progetto SvelteKit con Svelte 5
npm create svelte@latest my-svelte-app
cd my-svelte-app
# Seleziona: Skeleton project, TypeScript, ESLint, Prettier
npm install
# Avvia il dev server
npm run dev
Controleer of het project Svelte 5 gebruikt door de package.json:
{
"dependencies": {
"@sveltejs/kit": "^2.5.0",
"svelte": "^5.0.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"vite": "^5.0.0"
}
}
Maak je eerste component met Runen erin src/lib/components/Hello.svelte:
<script lang="ts">
// $props: tipo sicuro per le props del componente
const { name = 'Mondo' }: { name?: string } = $props();
// $state: stato locale reattivo
let clickCount = $state(0);
// $derived: valore computato da state e props
const message = $derived(
clickCount === 0
? `Ciao, ${name}!`
: `Ciao, ${name}! Hai cliccato ${clickCount} volt${clickCount === 1 ? 'a' : 'e'}`
);
</script>
<div class="hello">
<p>{message}</p>
<button onclick={() => clickCount++}>
Clicca qui
</button>
</div>
<style>
.hello {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
}
button {
margin-top: 0.5rem;
padding: 0.5rem 1rem;
}
</style>
SvelteKit: het full-stack-framework
Snel alleen en alleen de UI-laag. SvelteKit en het applicatieframework gebouwd op Svelte die routing, SSR (Server-Side Rendering), SSG (Static Site Generation), formulieracties en laden toevoegt functies voor het ophalen van gegevens. En het equivalent van Next.js voor React of Nuxt voor Vue.
De structuur van een SvelteKit-project volgt op bestanden gebaseerde conventies:
src/
├── routes/
│ ├── +layout.svelte # Layout globale
│ ├── +page.svelte # Homepage (/)
│ ├── about/
│ │ └── +page.svelte # Pagina /about
│ └── blog/
│ ├── +page.svelte # Lista articoli (/blog)
│ ├── +page.server.ts # Data fetching server-side
│ └── [slug]/
│ ├── +page.svelte # Articolo singolo (/blog/nome)
│ └── +page.server.ts
├── lib/
│ ├── components/ # Componenti condivisibili
│ └── utils/ # Utilita
└── app.html # Template HTML base
Wanneer kies je voor Svelte 5
Svelte 5 is de optimale keuze wanneer:
- Uploadprestaties zijn van cruciaal belang (mobiele, trage verbindingen)
- De bundelgrootte moet minimaal zijn
- Het team is bereid een ander mentaal model te leren dan React
- Je wilt een uitstekende DX (Developer Experience) met minder standaard
- Met SvelteKit bouwt u een site met veel inhoud die profiteert van SSR/SSG
Svelte 5 is mogelijk NIET de juiste keuze wanneer:
- Het team heeft sterke React-ervaring en de migratie zou te veel kosten
- Er wordt gezocht naar veel UI-componentbibliotheken (het React-ecosysteem is breder)
- Het moet integreren met bibliotheken die React gebruiken (headless UI, Radix, etc.)
Het mentale model: waar u rekening mee moet houden
Werken met Svelte 5 vereist het internaliseren van enkele fundamentele verschillen in vergelijking met frameworks gebaseerd op virtuele DOM:
- De compiler is uw hulpmiddel, niet de runtime. Wanneer iets niet werkt, zoals u verwacht, denk na over hoe de compiler uw code zal interpreteren, en niet over een weergavelus.
-
Runen communiceren met de compiler.
$state(),$derived()en de andere zijn geen eenvoudige functies: het zijn instructies voor de compiler over hoe om te gaan met reactiviteit. -
De responsiviteit is granulair van opzet. Werkt snel alleen bij wat er daadwerkelijk is
veranderd. Er is geen mechanisme waarmee u handmatig kunt optimaliseren
useMemoouseCallback. -
.svelte.ts-bestanden maken universele responsiviteit mogelijk. Je kunt Runen in elk spel gebruiken
bestand met extensie
.svelte.tso.svelte.js, niet alleen in de componenten.
Conclusies en volgende stappen
Svelte 5 vertegenwoordigt de belangrijkste evolutie van het raamwerk sinds de oprichting ervan. De aanpak compilergestuurd is niet nieuw, maar Runes nemen signaalgebaseerde responsiviteit buiten de grenzen van componenten, waardoor flexibelere en testbare architecturale patronen mogelijk worden. Het resultaat is een raamwerk dat combineert uitstekende prestaties, minimale bundel en een ontwikkelaarservaring zonder nutteloze standaardteksten.
Het volgende artikel in de serie gaat hier dieper op in $staat en $afgeleid: hoe het werkt
diepe responsiviteit via Proxy ES6, zoals $derived memoisatie implementeren, en hoe
gebruik Runen in TypeScript-bestanden die tussen componenten worden gedeeld.
Serie: Svelte 5 en frontend-compilergestuurd
- Artikel 1 (dit): Compilergestuurde aanpak en mentaal model
- Artikel 2: $state en $derived – Universele reactiviteit met runen
- Artikel 3: $effect en de levenscyclus – wanneer moet je het gebruiken (en wanneer niet)
- Artikel 4: SvelteKit SSR, streaming en laadfuncties
- Artikel 5: Overgangen en animaties in Svelte 5
- Artikel 6: Toegankelijkheid in Svelte: compilerwaarschuwingen en best practices
- Artikel 7: Mondiaal staatsbeheer: context, runen en winkels
- Artikel 8: Migreren van Svelte 4 naar Svelte 5 — Praktische gids
- Artikel 9: Testen in Svelte 5: Vitest, Testbibliotheek en Toneelschrijver







