Svelte 5: Podejście oparte na kompilatorze i model mentalny
Wyobraź sobie framework JavaScript, który całkowicie znika w czasie kompilacji. Brak bibliotek do pobrania, nie wirtualny DOM do uzgodnienia w czasie wykonywania, brak narzutu na framework widoczny w inspektorze przeglądarki. To i Svelte: nie ramy w tradycyjnym sensie, ale a kompilator, który przekształca komponenty .svelte w czystym i zoptymalizowanym JavaScript. Svelte 5, wydany w październiku 2024 r., przenosi ten model na wyższy poziom Wejdź na wyższy poziom dzięki Runom, uniwersalnemu systemowi reakcji opartemu na sygnałach, który zrewolucjonizował świat gdzie zarządzasz stanem w aplikacjach.
Jeśli pochodzisz z React, Vue lub Angular, model mentalny Svelte wymaga zmiany perspektywy. Nie o to chodzi nauczyć się nowego API, ale zrozumieć, że sam framework nie istnieje w czasie wykonywania. Ten przewodnik Ci pomoże zbudować ten model mentalny, badając, jak wewnętrznie działa kompilator Svelte i dlaczego Runes stanowią naturalną ewolucję tego podejścia.
Czego się nauczysz
- Jak kompilator Svelte przekształca komponenty w czysty JavaScript
- Ponieważ Svelte nie potrzebuje wirtualnego DOM
- Prawidłowy model mentalny do pracy ze Svelte 5
- Wprowadzenie do run i reaktywności opartej na sygnałach
- Porównanie wydajności z React i Vue (dane z lat 2025–2026)
- Jak stworzyć pierwszy komponent Svelte 5 za pomocą Run
Problem z wirtualnymi DOMami
Aby zrozumieć, dlaczego istnieje Svelte, musisz najpierw zrozumieć, co rozwiązuje. React, Vue i Angular używają a wirtualny DOM: Reprezentacja w pamięci rzeczywistego DOM, której framework używa do obliczeń różnice (różnicowanie) i zastosuj tylko niezbędne zmiany. Takie podejście ma intuicyjny sens – i Bardziej wydajna jest aktualizacja reprezentacji w pamięci niż bezpośrednie manipulowanie modelem DOM — ale wiąże się to z kosztami ukryte: wirtualne uzgadnianie DOM zawsze ma miejsce, nawet jeśli nic się nie zmieniło.
Rich Harris, twórca Svelte, ukuł termin „wirtualny DOM to czysty narzut„w artykuł z 2019 r., który wywołał ożywioną debatę w społeczności. Nie chodzi o to, że wirtualny DOM jest ogólnie powolny, ale wprowadza niepotrzebną pracę, którą kompilator mógłby wyeliminować.
Rozważmy komponent React, który wyświetla licznik:
// 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>
);
}
Za każdym razem, gdy zmienia się stan, React musi: Utworzyć nowy wirtualny DOM dla komponentu i porównać go z poprzedni (różnicowanie), ustal, co się zmieniło i na koniec zaktualizuj prawdziwy DOM. Kompilator Svelte już w czasie kompilacji wie, co może zmienić — tylko tekst akapitu — i generuje to bezpośrednio kod, aby go zaktualizować, bez żadnych kroków pośrednich.
Jak działa kompilator Svelte
Svelte komponent i .svelte który zawiera trzy opcjonalne sekcje: skrypt, szablon i
style. Podczas kompilacji kompilator analizuje ten plik i generuje JavaScript, który bezpośrednio manipuluje plikiem
DOM, z aktualizacjami szczegółowymi i chirurgicznymi.
<!-- Counter.svelte - Il componente sorgente -->
<script>
let count = $state(0);
</script>
<p>Contatore: {count}</p>
<button onclick={() => count++}>
Incrementa
</button>
Kompilator analizuje szablon i rozumie to {count} i jedyna część, która się zmienia.
Wygenerowany JavaScript zawiera bezpośrednio: Utwórz węzeł <p>, wstaw węzeł tekstowy,
i zarejestruj efekt, który aktualizuje tylko ten węzeł tekstowy, kiedy count zmiana. Brak wirtualnego DOM,
żadnego różnicowania, żadnego pojednania.
Skompilowany kod w uproszczeniu wygląda następująco:
// 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);
}
To jest sedno podejścia opartego na kompilatorze: kompilator dokładnie wie, co może zmienić i co generuje optymalny kod do obsługi, zamiast delegować tę pracę ogólnemu algorytmowi różnicującemu w czasie wykonywania.
Porównanie wielkości pakietu (2025)
Równoważny komponent TodoList tworzy pakiety JavaScript o bardzo różnych rozmiarach w głównych frameworkach:
- Reaguj 19 + ReagujDOM: ~42 KB spakowane w formacie gzip (włącznie ze środowiskiem wykonawczym)
- Wersja 3.5: ~22 KB spakowane w formacie gzip (włącznie ze środowiskiem wykonawczym)
- Angular 19 (samodzielny): ~35 KB spakowane w formacie gzip (włącznie ze środowiskiem wykonawczym)
- Szybkie 5: ~2-5 KB spakowane w formacie gzip (bez środowiska wykonawczego, tylko komponent)
W przypadku dużych aplikacji z wieloma komponentami przewaga jest mniejsza, ponieważ każdy komponent Svelte zawiera jego kod aktualizacji. Jednak w przypadku zastosowań średniej wielkości Svelte pozostaje ogólnym zwycięzcą pod względem ładunku do przeglądarki.
Zmiana paradygmatu w Svelte 5: Runy
Svelte 4 zastosował magiczny system reaktywności oparty na przypisaniach: każdej zmiennej w bloku
<script> był on automatycznie reaktywny, a kompilator przez cały czas śledził zależności
kompilacja. Działało to dobrze w prostych przypadkach, ale miało ważne ograniczenia: Reaktywność działała
tylko w komponentach .svelte, a magiczne zachowanie utrudniało zrozumienie kodu.
Svelte 5 wprowadza m.in Runy: funkcje specjalne z przedrostkiem $ którzy się komunikują
bezpośrednio z kompilatorem. Runy nie są normalnymi funkcjami — $state() to nie jest funkcja
który importuje i wywołuje — ale specjalna składnia rozpoznawana przez kompilator, podobna do how useState()
w React jest rozpoznawany przez transpiler do sprawdzania lint i typu, ale w rzeczywistości jest to zwykła funkcja.
Kluczowa różnica: Runy działają wszędzie, nie tylko w plikach .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
To radykalna zmiana w porównaniu do Svelte 4: logika biznesowa wraz z jej reaktywnością może żyć w oddzielnych modułach TypeScript, które można współdzielić między komponentami, testować w izolacji za pomocą normalnych testów jednostkowych, bez zależności od środowiska renderującego.
Cztery podstawowe runy
Svelte 5 wprowadza cztery główne runy, które obejmują większość przypadków użycia:
<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: Kluczowe różnice
Jeśli masz doświadczenie ze Svelte 4, Runy znacząco zmieniają składnię:
- Szybkie 4:
let count = 0;(ukryta magia) → Szybkie 5:let count = $state(0);(wyraźny) - Szybkie 4:
$: doubled = count * 2;→ Szybkie 5:const doubled = $derived(count * 2); - Szybkie 4:
export let prop;→ Szybkie 5:const { prop } = $props(); - Szybkie 4:
on:click={handler}→ Szybkie 5:onclick={handler}
Svelte 5 zachowuje kompatybilność wsteczną z Svelte 4 w „trybie starszej wersji”, więc migracja może przebiegać stopniowo.
Svelte 5 kontra React: praktyczne porównanie
Aby konkretnie zrozumieć różnicę w podejściu, przyjrzyjmy się temu samemu komponentowi zaimplementowanemu w 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..." />
Wersja Svelte 5 jest bardziej zwięzła nie dlatego, że jest „magiczna”: dzieje się tak dlatego, że kompilator zarządza synchronizacją
pomiędzy query i wprowadź przez bind:value, I $effect śledzić automatycznie
zależność od query bez konieczności jawnego deklarowania tego w tablicy zależności.
Rzeczywista wydajność: dane i testy porównawcze
Syntetyczne benchmarki często wprowadzają w błąd, ale dane z Test porównawczy JS Framework 2025 (działa na prawdziwym sprzęcie z intensywnymi operacjami DOM) plasuje Svelte 5 niezmiennie w górnym kwartylu dla prawie wszystkich testowanych operacji:
- Tworzenie 10 000 wierszy: Svelte 5 ~1,2x narzut w porównaniu z Vanilla JS, React ~2,1x
- Aktualizuj co 10 wiersz: Smukły 5 ~1,1x, Reaguj ~1,8x
- Wybierz wyróżnienie wiersza: Smukły 5 ~1,05x, Reaguj ~1,4x
- Pamięć po utworzeniu: Svelte 5 zużywa ~40% mniej pamięci niż React
Zaleta jest najbardziej widoczna na urządzeniach mobilnych z niższej półki, gdzie analizuje się i wykonuje JavaScript kosztują więcej. Na nowoczesnych komputerach stacjonarnych praktyczna różnica w przypadku typowych zastosowań jest często niewidoczna do użytkownika końcowego.
Tworzenie pierwszego szybkiego projektu 5
Najszybszym sposobem na rozpoczęcie pracy z Svelte 5 jest użycie SvelteKit, oficjalnego frameworka full-stack opartego na 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
Sprawdź, czy projekt korzysta z Svelte 5, zaznaczając plik package.json:
{
"dependencies": {
"@sveltejs/kit": "^2.5.0",
"svelte": "^5.0.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"vite": "^5.0.0"
}
}
Stwórz swój pierwszy komponent z Runami 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: Framework z pełnym stosem
Szybki sam i tylko warstwa interfejsu użytkownika. SvelteKit oraz framework aplikacji zbudowany na Svelte który dodaje routing, SSR (renderowanie po stronie serwera), SSG (generowanie witryny statycznej), akcje formularzy i ładowanie funkcje pobierania danych. Oraz odpowiednik Next.js dla React lub Nuxt dla Vue.
Struktura projektu SvelteKit jest zgodna z konwencjami opartymi na plikach:
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
Kiedy wybrać Svelte 5
Svelte 5 to optymalny wybór, gdy:
- Wydajność przesyłania jest krytyczna (mobile, wolne połączenia)
- Rozmiar pakietu musi być minimalny
- Zespół jest skłonny nauczyć się modelu mentalnego innego niż React
- Chcesz doskonałego DX (programisty) przy mniejszej liczbie szablonów
- Budujesz witrynę zawierającą dużą zawartość treści, która korzysta z SSR/SSG za pomocą SvelteKit
Svelte 5 może NIE być właściwym wyborem, gdy:
- Zespół ma duże doświadczenie w React, a migracja byłaby zbyt kosztowna
- Poszukiwanych jest wiele bibliotek komponentów interfejsu użytkownika (ekosystem React jest szerszy)
- Musi integrować się z bibliotekami obsługującymi React (bezgłowy interfejs użytkownika, Radix itp.)
Model mentalny: o czym należy pamiętać
Praca z Svelte 5 wymaga internalizacji pewnych podstawowych różnic w porównaniu do frameworków oparty na wirtualnym DOM:
- Kompilator jest Twoim narzędziem, a nie środowiskiem wykonawczym. Kiedy coś nie działa jak oczekujesz, zastanów się, jak kompilator zinterpretuje Twój kod, a nie pętlę renderującą.
-
Runy komunikują się z kompilatorem.
$state(),$derived()a pozostałe nie są prostymi funkcjami: są instrukcjami dla kompilatora, jak radzić sobie z reaktywnością. -
Responsywność jest z założenia szczegółowa. Szybko aktualizuje tylko to, co faktycznie się tam znajduje
zmieniony. Nie ma mechanizmu, za pomocą którego można ręcznie optymalizować
useMemoouseCallback. -
Pliki .svelte.ts umożliwiają uniwersalną responsywność. Możesz używać Run w dowolnym
plik z rozszerzeniem
.svelte.tso.svelte.jsnie tylko w komponentach.
Wnioski i dalsze kroki
Svelte 5 reprezentuje najbardziej znaczącą ewolucję frameworka od czasu jego powstania. Podejście sterowane przez kompilator nie jest niczym nowym, ale Runy wykorzystują responsywność opartą na sygnałach poza granicami komponentów, umożliwiając bardziej elastyczne i testowalne wzorce architektoniczne. Rezultatem jest struktura, która łączy doskonała wydajność, minimalny pakiet i doświadczenie programisty wolne od bezużytecznych schematów.
Następny artykuł z tej serii zawiera szczegółowe badania $stan i $pochodne: jak to działa
głęboka responsywność poprzez Proxy ES6, np $derived wdrożyć zapamiętywanie i jak
używaj run w plikach TypeScript współdzielonych między komponentami.
Seria: Svelte 5 i Frontend sterowane kompilatorem
- Artykuł 1 (ten): Podejście oparte na kompilatorze i model mentalny
- Artykuł 2: $stan i $pochodne — Uniwersalna reaktywność z runami
- Artykuł 3: $effect i cykl życia — kiedy go używać (a kiedy nie)
- Artykuł 4: SvelteKit SSR, funkcje przesyłania strumieniowego i ładowania
- Artykuł 5: Przejścia i animacje w Svelte 5
- Artykuł 6: Dostępność w Svelte: Ostrzeżenia kompilatora i najlepsze praktyki
- Artykuł 7: Globalne zarządzanie stanem: kontekst, runy i sklepy
- Artykuł 8: Migracja ze Svelte 4 do Svelte 5 – Poradnik praktyczny
- Artykuł 9: Testowanie w Svelte 5: Vitest, biblioteka testowa i dramaturg







