Svelte
Svelte is a UI framework that does most of its work at build time. Instead of shipping a runtime that diffs a virtual DOM in the browser, the Svelte compiler turns your components into small, efficient JavaScript that updates the exact DOM nodes that depend on changed state. The result is less code to download, fast updates, and components that read almost like plain HTML, CSS, and JavaScript.
Svelte was created by Rich Harris and is consistently among the most admired frameworks in developer surveys. Svelte 5 introduced runes — explicit reactivity primitives like $state and $derived — which make reactivity work the same way inside components and in regular .svelte.js modules. For routing, server rendering, and data loading, Svelte's official application framework is SvelteKit.
TL;DR
- Svelte is a compiler: components become targeted DOM updates with no virtual DOM.
- A component is a
.sveltefile with<script>, markup, and scoped<style>. - Svelte 5 runes:
$state(reactive state),$derived(computed values),$effect(side effects),$props(inputs). - Markup uses
{#if},{#each},{#await}blocks,bind:directives, and snippets for reusable markup. - Built-in transitions and animations, scoped CSS, and small bundles.
- Use SvelteKit for routing, SSR, and full-stack apps.
Quick Example
A todo component in Svelte 5 using runes, props, derived state, and an each block:
Core Concepts
The Compiler Approach
React and Vue ship a runtime that re-renders components and reconciles changes. Svelte analyzes components at build time and generates code that updates specific DOM nodes when specific state changes. The trade-off: very small output and fast updates, but behavior depends on the compiler understanding your code, which is why reactivity uses explicit runes.
Runes
Runes also work in .svelte.js/.svelte.ts files, so shared reactive state can live outside components.
Template Syntax
{#if cond}…{:else}…{/if},{#each items as item (item.id)},{#await promise}…{:then value}…{:catch err}.bind:value,bind:checked,bind:thisfor two-way binding and element references.class:active={isActive}andstyle:color={c}directives.- Snippets (
{#snippet row(item)}…{/snippet}and{@render row(item)}) replace slots for reusable markup and render props. - Event handlers are plain attributes:
onclick={handler}.
Stores and Shared State
Before runes, stores (writable, readable, derived) were the main way to share state; they're still supported and useful for streams of values. With Svelte 5, many apps share state through $state in modules or classes, and pass it via context (setContext/getContext). See State Management.
Styling, Transitions, and Animation
<style> blocks are scoped to the component automatically. Built-in transition:fade, in:fly, out:slide, and animate:flip make motion easy, and respect for prefers-reduced-motion can be added in a few lines.
SvelteKit
SvelteKit adds file-based routing, server-side rendering, static prerendering, load functions for data, form actions, and adapters for Vercel, Netlify, Cloudflare, Node, and static hosting. Most production Svelte apps use it.
Best Practices
Prefer $derived Over $effect
If a value can be computed from state, derive it. Use $effect only for genuine side effects like DOM APIs, logging, or subscriptions — syncing state in effects causes loops and bugs.
Key Your Each Blocks
{#each items as item (item.id)} lets Svelte preserve DOM and component state correctly when lists reorder.
Keep Components Small and Typed
Use lang="ts" and type $props(). Small components with clear props are easier to test and reuse.
Put Shared Logic in .svelte.ts Modules
Reactive classes or functions in modules keep state logic testable and reusable across components.
Use SvelteKit for Anything Beyond a Widget
Routing, SSR, and data loading are solved problems in SvelteKit; don't rebuild them.
Common Mistakes
Mixing Svelte 4 and 5 Reactivity Mentally
In Svelte 5 with runes, plain let variables aren't reactive and $: statements aren't used. Use $state and $derived.
Destructuring Reactive State
let { count } = counterState copies the current value and loses reactivity. Access properties through the object or use getters.
Updating State Inside $effect
Setting state that the same effect reads can create infinite loops. Derive instead.
Assuming a Huge Ecosystem
Svelte's ecosystem is healthy but smaller than React's. Check for maintained libraries (UI kits, data grids) before committing, or plan to wrap vanilla JS libraries.
Comparison
FAQ
What is Svelte?
Svelte is a compiler-based JavaScript framework for building user interfaces. It converts components into efficient JavaScript at build time, so apps ship less code and update the DOM directly without a virtual DOM.
What are runes in Svelte 5?
Runes are compiler-recognized symbols such as $state, $derived, $effect, and $props that declare reactive state, computed values, side effects, and component inputs explicitly.
Is Svelte better than React?
Svelte offers smaller bundles, less boilerplate, and simpler reactivity. React has a much larger ecosystem, more libraries, and more jobs. The better choice depends on team experience and project needs.
Do I need SvelteKit?
For a full application with routing, server rendering, or APIs, yes. For embedding a single interactive widget in an existing site, plain Svelte with Vite is enough.
Related Topics
- SvelteKit — Svelte's full-stack application framework
- React — The most popular alternative
- Vue — Another progressive, single-file-component framework
- State Management — Sharing state across components
- JavaScript — The language Svelte compiles to