Cos'è Svelte e cosa lo rende diverso
Cos'è Svelte e perché è un compilatore e non una libreria: niente DOM virtuale, bundle più piccoli, le rune di Svelte 5, SvelteKit e quando non sceglierlo.
Prima o poi incontri qualcuno che ti dice che con Svelte scrive metà del codice e il sito pesa un terzo. Poi leggi la documentazione, vedi una sintassi che sembra quasi HTML normale, e ti chiedi dove sia la fregatura. La fregatura non c'è, ma la differenza vera non è la sintassi: sta in quando succede il lavoro. In questo articolo trovi perché Svelte è un compilatore e non una libreria, cosa comporta davvero, cosa sono le rune e perché — nonostante tutto — probabilmente non lo sceglierai.
Cos'è
Svelte è un compilatore: prende i tuoi componenti e li trasforma, prima che il sito vada online, in normale codice JavaScript che aggiorna il DOM direttamente, invece di spedire al browser un motore che lo faccia a tempo di esecuzione.
Questa è tutta la differenza. Il resto discende da qui.
Compilatore contro libreria: cosa cambia davvero
Quando un utente apre una pagina fatta con React o Vue, il browser scarica due cose: il codice della tua applicazione e il framework stesso. Il framework è un programma vero e proprio che, a ogni cambiamento di stato, deve capire cosa aggiornare. Quel ragionamento avviene nel browser dell'utente, ogni volta.
Svelte lo fa prima, sulla tua macchina, in fase di build: il compilatore legge il componente, capisce staticamente quali pezzi di interfaccia dipendono da quali variabili, e genera codice che tocca esattamente quei nodi.
Un esempio. Questo componente:
<script>
let contatore = $state(0);
</script>
<button onclick={() => contatore++}>
Cliccato {contatore} volte
</button>
diventa, semplificando molto, qualcosa di concettualmente equivalente a:
// generato dal compilatore, non lo scrivi tu
const nodoTesto = /* il nodo di testo dentro il bottone */;
function aggiorna(nuovoValore) {
nodoTesto.data = `Cliccato ${nuovoValore} volte`;
}
Non c'è niente da confrontare, niente descrizione della pagina da ricostruire. Il codice sa già quale nodo toccare, perché lo ha deciso il compilatore.
Conseguenza diretta: niente DOM virtuale. Il DOM virtuale è la soluzione di React al problema "come faccio a sapere cosa è cambiato senza che me lo dica lo sviluppatore". Svelte quel problema non ce l'ha, perché la risposta l'ha calcolata in compilazione.
Se il concetto di DOM ti è ancora vago, chiariscilo prima: è l'oggetto che tutti questi strumenti manipolano, con strategie diverse.
Cosa comporta e cosa NON comporta
Qui vale la pena essere precisi, perché è l'argomento su cui circolano più affermazioni entusiaste che non reggono.
Cosa comporta davvero:
- Il bundle di partenza è più piccolo. Non spedisci un motore di reattività: spedisci solo il codice generato dai tuoi componenti. Su una pagina semplice la differenza è netta e si vede sui tempi di caricamento e sui Core Web Vitals.
- Meno JavaScript da analizzare e avviare. Il costo di un pacchetto non è solo scaricarlo: il browser deve interpretarlo ed eseguirlo. È il costo che si sente di più su telefoni economici e reti lente.
- Meno codice scritto a mano. La sintassi è compatta e non ci sono cerimonie: niente
useState, niente funzioniset, niente array di dipendenze da tenere allineati. - Nessuna ottimizzazione manuale. Il capitolo memorizzazione di React —
memo,useMemo,useCallback— semplicemente non esiste.
Cosa NON comporta, e va detto:
- Non è "sempre più veloce". Il vantaggio sta nel codice del framework che non spedisci, e quel risparmio è una costante: pesa molto su un'applicazione piccola, molto meno su una dieci volte più grande. Il codice generato da Svelte cresce con il numero di componenti, mentre il runtime di React è costo fisso: su progetti grandi il divario si assottiglia.
- Non risolve i problemi veri di prestazioni. Immagini non ottimizzate, query lente e chiamate di rete mal gestite pesano ordini di grandezza più della scelta del framework: vedi come velocizzare un sito.
- Non elimina la fase di build. Il codice va compilato: non è una libreria che includi con un tag script.
- Non fa sparire i bug di stato. Uno stato mal progettato è mal progettato ovunque.
| React | Svelte | |
|---|---|---|
| Quando avviene il lavoro | A tempo di esecuzione | In compilazione |
| Cosa scarica l'utente | Runtime + codice app | Quasi solo codice app |
| Aggiornamento del DOM | Confronto col DOM virtuale | Diretto sul nodo |
| Ottimizzazione manuale | Spesso necessaria | Non prevista |
| Righe di codice tipiche | Di più | Di meno |
| Ecosistema e lavoro | Enorme | Piccolo |
Le rune di Svelte 5
Fino alla versione 4, la reattività in Svelte era implicita: assegnavi una variabile e il compilatore capiva che era reattiva.
// Svelte 4: reattività implicita
let contatore = 0;
$: doppio = contatore * 2;
Sembrava magia ed era comodissimo, finché non usciva dal componente: il compilatore poteva fare quella deduzione solo dentro un file .svelte, e appena spostavi la logica in un .js normale per riusarla la reattività spariva. In più $: era ambiguo — a volte dichiarava un valore derivato, a volte eseguiva un effetto collaterale.
Svelte 5 ha sostituito quel meccanismo con le rune: funzioni speciali che dichiarano esplicitamente cosa è reattivo.
<script>
let quantita = $state(1);
let prezzo = $state(20);
let totale = $derived(quantita * prezzo);
$effect(() => {
console.log("il totale è cambiato:", totale);
});
</script>
<input type="number" bind:value={quantita} />
<p>Totale: {totale} €</p>
Tre cose da notare.
$state rende esplicito cosa è reattivo. Non devi più indovinare se una variabile lo sia: c'è scritto.
$derived è un valore calcolato che si aggiorna da solo quando cambiano le sue dipendenze. Non è uno stato separato da tenere in sincronia: è la soluzione all'errore classico di duplicare nello stato un'informazione che si può calcolare.
Le rune funzionano fuori dai componenti. È il vero motivo del cambio: puoi mettere la logica in un file .svelte.js e riusarla in dieci componenti, e resta reattiva.
// contatore.svelte.js
export function creaContatore(iniziale = 0) {
let valore = $state(iniziale);
return {
get valore() {
return valore;
},
incrementa: () => valore++,
};
}
Il prezzo è un po' di magia in meno e qualche parentesi in più. È stato un cambiamento discusso — parte della comunità amava la sintassi precedente proprio perché non aveva cerimonie — ma il codice nuovo si scrive così.
La sintassi dei template
Il resto di Svelte è deliberatamente ridotto. Il template è HTML con qualche blocco di controllo.
<script>
let prodotti = $state([
{ id: 1, nome: "Tastiera", prezzo: 49 },
{ id: 2, nome: "Monitor", prezzo: 199 },
]);
</script>
{#if prodotti.length > 0}
<ul>
{#each prodotti as prodotto (prodotto.id)}
<li>{prodotto.nome} — {prodotto.prezzo} €</li>
{/each}
</ul>
{:else}
<p>Nessun prodotto</p>
{/if}
<style>
li { padding: 0.25rem 0; }
</style>
Lo stile è isolato per impostazione predefinita, senza scrivere nulla: quel li vale solo qui. E bind:value fa il collegamento a doppio senso sui campi dei moduli, come v-model in Vue.
Quel (prodotto.id) in {#each} è la chiave della lista: senza, Svelte associa gli elementi per posizione e quando riordini o cancelli ottieni le stesse stranezze che in React danno le chiavi sbagliate.
SvelteKit
Svelte da solo gestisce l'interfaccia. Per un'applicazione completa serve il meta-framework ufficiale: SvelteKit, che sta a Svelte come Next.js sta a React.
Ti dà routing basato sui file, caricamento dati lato server, endpoint API e i vari modelli di rendering — statico, lato server, ibrido — spiegati in SSG, SSR e ISR. Chi sceglie Svelte per un progetto reale parte quasi sempre da SvelteKit, non da Svelte nudo.
Errori comuni che fanno perdere ore
Mescolare sintassi di Svelte 4 e 5. Metà delle guide online usa export let per le proprietà e $: per i valori derivati; in Svelte 5 servono $props() e $derived. Controlla la data di quello che leggi: è la prima causa di codice che "non funziona e non si capisce perché".
Usare $effect per calcolare valori. Identico all'errore con useEffect in React:
// no: stato inutile, aggiornamenti in più
let totale = $state(0);
$effect(() => {
totale = quantita * prezzo;
});
// sì: è solo un calcolo
let totale = $derived(quantita * prezzo);
$effect serve per sincronizzarti con qualcosa fuori da Svelte: un timer, un'API del browser, una libreria di terze parti.
Aspettarsi che uno stato reattivo attraversi un confine non reattivo. Se passi il valore di uno $state a una funzione normale, passi il valore in quel momento, non il collegamento. Serve passare una funzione che lo legge.
Scegliere Svelte per i benchmark. Vedi la sezione successiva: è quasi sempre la ragione sbagliata.
Quando Svelte non è la scelta giusta
Questa è la parte onesta, e va detta senza attenuanti.
Il motivo per cui non sceglierai Svelte non è tecnico. Tecnicamente è ottimo: il modello è pulito, il codice è più corto, il risultato è più leggero, SvelteKit è fatto bene. Il problema è tutto intorno.
L'ecosistema è molto più piccolo. Componenti pronti, librerie di grafici, editor di testo ricco, integrazioni con servizi esterni: per React esiste tutto, in più versioni, testato da migliaia di progetti. Per Svelte spesso esiste qualcosa, a volte mantenuto da una persona sola. Quando ti serve un calendario complesso di venerdì pomeriggio, la differenza si sente.
Il mercato del lavoro italiano è ancora più impietoso. Le offerte che chiedono Svelte si contano. Se stai imparando per lavorare, sceglierlo al posto di React ti restringe le possibilità. Il quadro completo è in React, Vue o Angular.
Trovare risposte è più difficile. Per ogni problema in React esistono dieci discussioni e una risposta accettata; in Svelte a volte c'è solo la documentazione, ottima ma incompleta sul caso strano che ti è capitato.
Quando invece ha senso: progetti personali, prototipi, MVP da mettere in piedi in fretta, siti dove il peso del JavaScript conta davvero, widget da incastrare in pagine esistenti, e squadre piccole che decidono da sé il proprio stack.
Il criterio onesto: se stai scegliendo per imparare e lavorare, React. Se stai scegliendo per un progetto tuo o di un team autonomo e il peso conta, Svelte è un'ottima scelta e ti farà scrivere meno codice.
In sintesi
Svelte è un compilatore, non una libreria che gira nel browser. Sposta il lavoro dalla fase di esecuzione a quella di build, e non spedisce all'utente un motore di reattività.
Da qui i bundle più piccoli e l'assenza di DOM virtuale, ma non una superiorità automatica su tutto: su applicazioni grandi il divario si assottiglia, e i veri colli di bottiglia di un sito lento stanno altrove.
Le rune di Svelte 5 — $state, $derived, $effect — hanno sostituito la reattività implicita per renderla esplicita e, soprattutto, riusabile fuori dai componenti.
Per un'applicazione completa si usa SvelteKit, non Svelte da solo.
Il motivo per cui probabilmente non lo sceglierai non è tecnico ma di contorno: ecosistema più piccolo, meno risposte online e un mercato del lavoro italiano quasi inesistente rispetto a React.
Per il confronto con gli altri due grandi, vedi cos'è Vue e cos'è Angular. Per inquadrare la scelta nel progetto intero, come scegliere lo stack per una web app.