--- name: svelte-migrate description: Migrate a Svelte 4 component to Svelte 5 runes syntax. Use when asked to migrate, convert, or upgrade a .svelte file to Svelte 5. --- # Svelte 4 to 5 Migration Migrate individual Svelte files from v4 to v5 runes syntax. ## Usage When the user provides a file path, migrate that specific file following the patterns below. ## Migration Patterns ### 1. Props: `export let` → `$props()` **Before:** ```svelte ``` **After:** ```svelte ``` ### 2. State: `let` → `$state()` Only reactive variables that are reassigned or mutated need `$state()`. **Before:** ```svelte ``` **After:** ```svelte ``` ### 3. Derived Values: `$:` → `$derived()` **Before:** ```svelte ``` **After:** ```svelte ``` For complex derivations use `$derived.by()`: **Before:** ```svelte ``` **After:** ```svelte ``` ### 4. Side Effects: `$:` statements → `$effect()` **Before:** ```svelte ``` **After:** ```svelte ``` ### 5. Event Handlers: `on:event` → `onevent` **Before:** ```svelte ``` **After:** ```svelte ``` Event modifiers like `|preventDefault`, `|stopPropagation` must be handled manually in the handler. ### 6. Component Events: `createEventDispatcher` → callback props **Before:** ```svelte ``` **After:** ```svelte ``` **Parent component changes:** Before: `` After: `` ### 7. Forwarding Events: `on:event` → explicit handler **Before:** ```svelte ``` **After:** ```svelte ``` ### 8. Slots → Snippets **Default slot:** Before: ```svelte ``` After: ```svelte {@render children?.()} ``` **Named slots:** Before: ```svelte ``` After: ```svelte {@render header?.()} {@render children?.()} {@render footer?.()} ``` **Slots with props (let:):** Before: ```svelte {index}: {item.name} ``` After: ```svelte {@render children?.({ item: currentItem, index: i })} {#snippet children({ item, index })} {index}: {item.name} {/snippet} ``` ### 9. Bindable Props: `bind:` → `$bindable()` **Before:** ```svelte ``` **After:** ```svelte ``` ### 10. Lifecycle: `beforeUpdate`/`afterUpdate` → `$effect` **Before:** ```svelte ``` **After:** ```svelte ``` **IMPORTANT: `onMount` and `onDestroy` remain valid and should be preserved!** - Use `onMount` for initialization logic that should only run once when the component first mounts - Use `$effect` for reactive side effects that should re-run when dependencies change - Never convert `onMount` to `$effect` unless the logic genuinely needs to be reactive **Examples:** Keep as `onMount`: ```svelte // ✅ One-time initialization - keep as onMount onMount(() => { if (query) { $filters = toListWorkflowFilters(query, $searchAttributes); } }); ``` Convert to `$effect`: ```svelte // ✅ Reactive side effect - convert to $effect $effect(() => { document.title = `Count: ${count}`; // re-runs when count changes }); ``` ### 11. Dynamic Components: `` → direct usage **Before:** ```svelte ``` **After:** ```svelte ``` Or with conditional: ```svelte {#if Component} {/if} ``` ### 12. `class:` Directive → Conditional Classes The `class:` directive still works but consider using conditional expressions: **Before:** ```svelte
``` **After (either works):** ```svelte
``` ### 13. App State **Before:** ```svelte import {page} from '$app/stores' ``` **After:** ```svelte import {page} from '$app/state' ``` ## Workflow 1. Read the file to understand its current structure 2. Identify all Svelte 4 patterns that need migration 3. Apply transformations systematically: - Props first (export let → $props) - State variables (let → $state where needed) - Derived values ($: assignments → $derived) - Side effects ($: statements → $effect) - Event handlers (on: → on) - Component events (dispatch → callback props) - Slots (slot → snippets) 4. Update imports (add Snippet type if needed, remove createEventDispatcher if no longer used) 5. Ensure TypeScript types are correct 6. Run `pnpm check` to verify no type errors ## Important Notes - Keep `onMount` and `onDestroy` - they're still valid - `context="module"` scripts are now `