Svelte 5: Abordarea condusă de compilator și modelul mental
Imaginați-vă un cadru JavaScript care dispare complet în timpul construirii. Nu există biblioteci de descărcat, nu DOM virtual care urmează să fie reconciliat în timpul execuției, fără cadru general vizibil în inspectorul browserului. Aceasta și Svelte: nu un cadru în sensul tradițional, ci un compilator care transformă componente .svelte în JavaScript pur și optimizat. Svelte 5, lansat în octombrie 2024, aduce acest model la a treci la nivel cu Runes, un sistem universal de reactivitate bazat pe semnal, care a revoluționat lumea unde gestionați starea în aplicații.
Dacă vii de la React, Vue sau Angular, modelul mental al lui Svelte necesită o schimbare de perspectivă. Nu este vorba despre asta pentru a învăța un nou API, dar pentru a înțelege că cadrul în sine nu există la runtime. Acest ghid vă ajută pentru a construi acel model mental, explorând modul în care compilatorul Svelte funcționează intern și de ce Runes reprezintă evoluţia firească a acestei abordări.
Ce vei învăța
- Cum compilatorul Svelte transformă componentele în JavaScript pur
- Pentru că Svelte nu are nevoie de un DOM virtual
- Modelul mental corect pentru lucrul cu Svelte 5
- Introducere în rune și reactivitate bazată pe semnal
- Comparație de performanță cu React și Vue (date 2025-2026)
- Cum se creează prima componentă Svelte 5 cu Runes
Problema cu DOM-urile virtuale
Pentru a înțelege de ce există Svelte, trebuie mai întâi să înțelegeți ce rezolvă. React, Vue și Angular folosesc toate a DOM virtual: O reprezentare în memorie a DOM-ului real pe care cadrul îl folosește pentru a calcula diferențele (diferențele) și aplicați numai modificările necesare. Această abordare are sens intuitiv — și Este mai eficient să actualizați o reprezentare în memorie decât să manipulați DOM-ul direct - dar are un cost ascuns: reconcilierea DOM virtuală are loc întotdeauna, chiar și atunci când nimic nu s-a schimbat.
Rich Harris, creatorul lui Svelte, a inventat termenul „DOM virtual este pur și simplu overhead"în un articol din 2019 care a stârnit o dezbatere aprinsă în comunitate. Ideea nu este că DOM-ul virtual este lent în general, dar introduce lucrări inutile pe care compilatorul le-ar putea elimina.
Luați în considerare o componentă React care afișează un contor:
// 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>
);
}
De fiecare dată când starea se schimbă, React trebuie: să creeze un nou DOM virtual pentru componentă, cu care să-l compare cea precedentă (diferență), determinați ce s-a schimbat și, în sfârșit, actualizați DOM-ul real. Compilatorul Svelte știe deja la momentul construirii ce se poate schimba - doar textul paragrafului - și îl generează direct cod pentru a-l actualiza, fără nici un pas intermediar.
Cum funcționează compilatorul Svelte
O componentă Svelte și a .svelte care conține trei secțiuni opționale: script, template și
stiluri. În timpul construcției, compilatorul analizează acest fișier și generează JavaScript care manipulează direct fișierul
DOM, cu actualizări granulare și chirurgicale.
<!-- Counter.svelte - Il componente sorgente -->
<script>
let count = $state(0);
</script>
<p>Contatore: {count}</p>
<button onclick={() => count++}>
Incrementa
</button>
Compilatorul analizează șablonul și înțelege asta {count} și singura parte care se schimbă.
JavaScript generat conține direct: Creați nodul <p>, inserați un nod text,
și înregistrați un efect care actualizează doar acel nod text atunci când count schimba. Fără DOM virtual,
fără diferențe, fără reconciliere.
Codul compilat, simplificat, arată astfel:
// 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);
}
Aceasta este inima abordării bazate pe compilator: compilatorul știe exact ce poate schimba și ce generează codul optim pentru a-l gestiona, în loc să delegeți această muncă unui algoritm de diferențiere generic în timpul execuției.
Comparația dimensiunilor pachetului (2025)
O componentă echivalentă TodoList produce pachete JavaScript de dimensiuni foarte diferite în cadrul principalelor cadre:
- React 19 + ReactDOM: ~42 KB arhivat (timpul de rulare inclus)
- Vedere 3.5: ~22 KB arhivat (timpul de rulare inclus)
- Angular 19 (autonom): ~35 KB arhivat (timpul de rulare inclus)
- Rapid 5: ~2-5 KB gzipped (fără runtime, doar componenta)
Pentru aplicații mari cu multe componente, avantajul este redus deoarece fiecare componentă Svelte include codul său de actualizare. Dar pentru aplicațiile de dimensiuni medii, Svelte rămâne câștigătorul general în ceea ce privește sarcina utilă pentru browser.
Schimbarea de paradigmă a lui Svelte 5: Runele
Svelte 4 a folosit un sistem magic de reactivitate bazat pe atribuiri: fiecare variabilă din bloc
<script> a fost reactiv automat, iar compilatorul a urmărit dependențele pe tot parcursul
construirea. Acest lucru a funcționat bine pentru cazuri simple, dar a avut limitări importante: reactivitatea a funcționat
numai în cadrul componentelor .svelte, iar comportamentul magic a făcut codul dificil de raționat.
Svelte 5 introduce i Rune: funcții speciale cu prefix $ care comunică
direct cu compilatorul. Runele nu sunt funcții normale - $state() nu este o funcție
care importă și apelează — dar o sintaxă specială recunoscută de compilator, similar cu cum useState()
în React este recunoscut de transpiler pentru verificări de scame și tip, dar este de fapt o funcție obișnuită.
Diferența cheie: runele funcționează pretutindeni, nu doar în fișierele .svelte:
// 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
Aceasta este o schimbare radicală față de Svelte 4: logica de afaceri cu reactivitatea sa poate trăi în module TypeScript separate, care pot fi partajate între componente, pot fi testate izolat cu testele unitare normale, fără dependențe de un mediu de randare.
Cele patru rune fundamentale
Svelte 5 introduce patru rune principale care acoperă majoritatea cazurilor de utilizare:
<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 vs Svelte 5: diferențe cheie
Dacă aveți experiență cu Svelte 4, Runes schimbă semnificativ sintaxa:
- Rapid 4:
let count = 0;(magie implicită) → Rapid 5:let count = $state(0);(explicit) - Rapid 4:
$: doubled = count * 2;→ Rapid 5:const doubled = $derived(count * 2); - Rapid 4:
export let prop;→ Rapid 5:const { prop } = $props(); - Rapid 4:
on:click={handler}→ Rapid 5:onclick={handler}
Svelte 5 menține compatibilitatea cu Svelte 4 în „modul moștenit”, astfel încât migrarea poate fi treptată.
Svelte 5 vs React: o comparație practică
Pentru a înțelege în mod concret diferența de abordare, să vedem aceeași componentă implementată în React și 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..." />
Versiunea Svelte 5 este mai concisă nu pentru că este „magică”: este pentru că compilatorul gestionează sincronizarea
intre query și introduceți prin bind:value, Și $effect urmăriți automat
dependenta de query fără a fi nevoie să-l declare în mod explicit în tabloul de dependențe.
Performanță reală: date și benchmark
Benchmark-urile sintetice sunt adesea înșelătoare, dar datele de la JS Framework Benchmark 2025 (funcționând pe hardware real cu operațiuni DOM intensive) arată Svelte 5 în mod constant în quartila superior pentru aproape toate operațiunile testate:
- Crearea a 10.000 de rânduri: Svelte 5 ~1,2x peste cap vs Vanilla JS, React ~2,1x
- Actualizați la fiecare al 10-lea rând: Svelte 5 ~1,1x, React ~1,8x
- Selectați evidențierea rândului: Svelte 5 ~1,05x, React ~1,4x
- Memorie după creare: Svelte 5 folosește cu ~40% mai puțină memorie decât React
Avantajul este cel mai pronunțat pe dispozitivele mobile low-end, unde analiza și execuția JavaScript costă mai mult. Pe desktop-urile moderne, diferența practică pentru aplicațiile tipice este adesea invizibilă către utilizatorul final.
Crearea primului proiect rapid 5
Cea mai rapidă modalitate de a începe cu Svelte 5 este să utilizați SvelteKit, cadrul oficial full-stack bazat pe 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
Verificați dacă proiectul folosește Svelte 5 bifând package.json:
{
"dependencies": {
"@sveltejs/kit": "^2.5.0",
"svelte": "^5.0.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"vite": "^5.0.0"
}
}
Creați-vă prima componentă cu Runes în 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: Cadrul Full-Stack
Rapid singur și doar stratul UI. SvelteKit și cadrul de aplicație construit pe Svelte care adaugă rutare, SSR (Server-Side Rendering), SSG (Static Site Generation), acțiuni de formular și încărcare funcții pentru preluarea datelor. Și echivalentul Next.js pentru React sau Nuxt pentru Vue.
Structura unui proiect SvelteKit urmează convențiile bazate pe fișiere:
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
Când să alegi Svelte 5
Svelte 5 este alegerea optimă atunci când:
- Performanța de încărcare este critică (mobile, conexiuni lente)
- Dimensiunea pachetului trebuie să fie minimă
- Echipa este dispusă să învețe un model mental diferit de React
- Vrei un DX (Developer Experience) excelent cu mai puțină boilerplate
- Construiți un site cu conținut intens, care beneficiază de SSR/SSG cu SvelteKit
Svelte 5 poate să NU fie alegerea potrivită atunci când:
- Echipa are o experiență puternică în React și migrarea ar costa prea mult
- Sunt căutate multe biblioteci de componente UI (ecosistemul React este mai larg)
- Trebuie să se integreze cu bibliotecile care acceptă React (interfață de utilizare fără cap, Radix etc.)
Modelul mental: de ce să țineți cont
Lucrul cu Svelte 5 necesită interiorizarea unor diferențe fundamentale în comparație cu cadrele bazat pe DOM virtual:
- Compilatorul este instrumentul tău, nu timpul de execuție. Când ceva nu merge ca vă așteptați, gândiți-vă la modul în care compilatorul vă va interpreta codul, nu o buclă de randare.
-
Runele comunică cu compilatorul.
$state(),$derived()iar celelalte nu sunt funcții simple: sunt instrucțiuni pentru compilator despre cum să gestioneze reactivitatea. -
Reactivitatea este granulară prin proiectare. Actualizează rapid doar ceea ce este de fapt acolo
schimbat. Nu există niciun mecanism cu care să optimizați manual
useMemoouseCallback. -
Fișierele .svelte.ts permit răspunsul universal. Puteți folosi Runes în orice
fișier cu extensie
.svelte.tso.svelte.js, nu doar în componente.
Concluzii și pașii următori
Svelte 5 reprezintă cea mai semnificativă evoluție a cadrului de la crearea sa. Abordarea condus de compilator nu este nou, dar Runes preia capacitatea de răspuns bazată pe semnal în afara limitelor componentelor, permițând modele arhitecturale mai flexibile și mai testabile. Rezultatul este un cadru care combină performanță excelentă, pachet minim și o experiență de dezvoltator fără boilerplate inutile.
Următorul articol din serie explorează în profunzime $state și $derivat: cum funcționează
reacție profundă prin Proxy ES6, cum ar fi $derived implementați memorarea și cum
utilizați Rune în fișierele TypeScript partajate între componente.
Seria: Svelte 5 și Frontend Compiler-Driven
- Articolul 1 (acesta): Abordare condusă de compilator și model mental
- Articolul 2: $state și $derived — Reactivitate universală cu rune
- Articolul 3: $effect și ciclul de viață – Când să-l utilizați (și când nu)
- Articolul 4: SvelteKit SSR, Streaming și Funcții de încărcare
- Articolul 5: Tranziții și animații în Svelte 5
- Articolul 6: Accesibilitate în Svelte: Avertismente ale compilatorului și cele mai bune practici
- Articolul 7: Managementul global al statului: context, rune și magazine
- Articolul 8: Migrarea de la Svelte 4 la Svelte 5 — Ghid practic
- Articolul 9: Testarea în Svelte 5: Vitest, Biblioteca de testare și dramaturg







