# Svelte 4 to Svelte 5 Migration Reference ## Table of Contents - [Migrating Reactive Statements](#migrating-reactive-statements) - [Migrating Stores to Runes](#migrating-stores-to-runes) --- ## Migrating Reactive Statements Svelte 5 replaces `$:` with `$derived` (for values) and `$effect` (for side effects). ### Computed Values: $: to $derived **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Complex Computed Values: $derived.by **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Side Effects: $: to $effect **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Conditional Side Effects **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Props Migration **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Effect with Cleanup **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Migration Cheat Sheet | Svelte 4 Pattern | Svelte 5 Replacement | |------------------|----------------------| | `let x = 0` (in component) | `let x = $state(0)` | | `export let prop` | `let { prop } = $props()` | | `$: derived = expr` | `let derived = $derived(expr)` | | `$: { complex }` (value) | `let x = $derived.by(() => { ... })` | | `$: console.log(x)` | `$effect(() => console.log(x))` | | `$: if (x) { ... }` | `$effect(() => { if (x) { ... } })` | | `$: document.title = x` | `$effect(() => { document.title = x })` | ### Automated Migration ```bash npx sv migrate svelte-5 ``` --- ## Migrating Stores to Runes Svelte 5 runes can replace most store use cases with simpler, more direct reactive state. ### Local Component State **Svelte 4:** ```svelte ``` **Svelte 5:** ```svelte ``` ### Shared State Across Components **Svelte 4 (stores.ts):** ```ts import { writable } from 'svelte/store'; export const user = writable(null); export const theme = writable('light'); ``` **Svelte 5 (state.svelte.ts):** ```ts export const user = $state(null); export const theme = $state({ current: 'light' as 'light' | 'dark' }); export function setTheme(newTheme: 'light' | 'dark') { theme.current = newTheme; } ``` ```svelte

Theme: {theme.current}

``` ### Derived Store to $derived **Svelte 4:** ```ts import { writable, derived } from 'svelte/store'; export const items = writable([]); export const completedCount = derived(items, $items => $items.filter(i => i.done).length ); ``` **Svelte 5:** ```ts // state.svelte.ts export const items = $state([]); export function getCompletedCount() { return items.filter(i => i.done).length; } ``` ```svelte ``` ### Custom Store to Reactive Class **Svelte 4:** ```ts function createCounter() { const { subscribe, set, update } = writable(0); return { subscribe, increment: () => update(n => n + 1), decrement: () => update(n => n - 1), reset: () => set(0) }; } export const counter = createCounter(); ``` **Svelte 5:** ```ts // counter.svelte.ts class Counter { value = $state(0); increment() { this.value++; } decrement() { this.value--; } reset() { this.value = 0; } } export const counter = new Counter(); ``` ```svelte

{counter.value}

``` ### Async State Pattern **Svelte 5:** ```ts // api.svelte.ts export const state = $state({ data: null as Data | null, loading: false, error: null as Error | null }); export async function fetchData() { state.loading = true; state.error = null; try { const res = await fetch('/api/data'); state.data = await res.json(); } catch (e) { state.error = e as Error; } finally { state.loading = false; } } ``` ### When to Still Use Stores 1. **Library interop** - Libraries that expect Svelte stores 2. **Legacy code** - Gradual migration 3. **Observable patterns** - When you need the subscribe API 4. **Server-side rendering** - Stores have built-in SSR handling ### Store to Rune Cheat Sheet | Store Pattern | Rune Replacement | |---------------|------------------| | `writable(value)` | `$state(value)` | | `$store` (auto-subscribe) | Direct access to `$state` value | | `store.set(x)` | `state = x` | | `store.update(fn)` | Direct mutation or reassignment | | `derived(store, fn)` | `$derived(fn())` in component | | `readable(value, start)` | `$state` + `$effect` for setup |