Back

Best Practices für die Arbeit mit Svelte

Best Practices für die Arbeit mit Svelte

Wenn Sie die Grundlagen von Svelte hinter sich gelassen und mit dem Bau echter Anwendungen begonnen haben, ist Ihnen vermutlich aufgefallen, dass die offizielle Dokumentation zwar erklärt, was die einzelnen Features tun, aber nicht immer, wann oder warum man sie einsetzen sollte. Dieser Artikel konzentriert sich auf Best Practices für Svelte 5, die Wartbarkeit, Performance und Klarheit in Produktivcode verbessern – wir setzen voraus, dass Sie bereits verstehen, wie Komponenten und Reaktivität funktionieren.

Wichtige Erkenntnisse

  • Verwenden Sie $state nur dann, wenn ein Wert UI-Updates auslöst, und greifen Sie zu $state.raw, wenn Sie Werte ersetzen statt mutieren.
  • Bevorzugen Sie $derived gegenüber $effect für berechnete Werte; reservieren Sie $effect für die Synchronisation mit externen Systemen.
  • Vermeiden Sie modul-globalen State in SSR-Umgebungen. Nutzen Sie Sveltes Context-API mit klassenbasiertem $state für typsicheren, request-bezogenen Shared State.
  • In SvelteKit verwenden Sie +page.server.js für serverseitige Seitendaten und +server.js für eigenständige API-Endpunkte.
  • Setzen Sie in neuem Code auf moderne Svelte-5-Syntax (onclick, {#snippet}, $props()) anstelle von Legacy-Patterns.

Svelte 5 Runes: Präzise einsetzen

Svelte 5 Runes sind das primäre Reaktivitätsmodell, und sie korrekt einzusetzen ist wichtiger, als sie überall zu verwenden.

Greifen Sie nur dann zu $state, wenn eine Variable UI-Updates auslösen muss. Für alles andere sind einfache Variablen günstiger und klarer.

Wenn Ihr State ein großes Objekt oder Array ist, das ersetzt statt mutiert wird, verwenden Sie stattdessen $state.raw:

// ❌ Unnötiger Proxy-Overhead für API-Daten, die Sie nur neu zuweisen
let users = $state(await fetchUsers());

// ✅ Keine Proxy-Kosten, wenn Sie ersetzen statt mutieren
let users = $state.raw(await fetchUsers());

Verwenden Sie $state, wenn Sie verschachtelte Eigenschaften direkt mutieren müssen (z. B. cart.items[0].quantity++). Verwenden Sie $state.raw, wenn Sie den gesamten Wert austauschen.

Bevorzugen Sie $derived gegenüber $effect für berechnete Werte

Dies ist einer der häufigsten Fehler in der modernen Svelte-Entwicklung:

let num = $state(0);

// ❌ Vermeiden — erzeugt einen unnötigen Side Effect
let square = $state(0);
$effect(() => { square = num * num; });

// ✅ Korrekt — deklarativ und mit Dependency-Tracking
let square = $derived(num * num);

$effect ist ein Escape Hatch. Reservieren Sie es für die Synchronisation mit externen Systemen (wie D3) und ziehen Sie {@attach} für DOM-nahe Integrationen in Betracht, wo es natürlich passt.

Props als dynamisch behandeln

Aus Props abgeleitete Werte sollten $derived verwenden, nicht eine einfache Zuweisung:

let { type } = $props();

// ✅ Bleibt synchron, wenn sich `type` ändert
let color = $derived(type === 'danger' ? 'red' : 'green');

Typsicherer Context statt geteilter Module

Für State, der über einen Komponenten-Teilbaum geteilt wird, sollten Sie Sveltes Context-API gegenüber modul-globalem State bevorzugen. Modul-State bleibt in SSR-Umgebungen über Requests hinweg bestehen, was dazu führen kann, dass Daten zwischen Nutzern leaken.

Das moderne Pattern verwendet eine Klasse mit $state-Feldern:

// lib/theme.svelte.ts
import { getContext, setContext } from 'svelte';

class ThemeContext {
  current = $state('light');

  toggle() {
    this.current = this.current === 'light' ? 'dark' : 'light';
  }
}

const KEY = Symbol('theme');

export const setTheme = () => setContext(KEY, new ThemeContext());

export const getTheme = () => getContext<ThemeContext>(KEY);

So erhalten Sie Typsicherheit, reaktiven State und sauberes SSR-Scoping in einem einzigen Pattern.

SvelteKit Data Loading: Das richtige Pattern wählen

Ein häufiger Punkt der Verwirrung in SvelteKit ist, wann man +page.server.js und wann +server.js verwenden sollte:

SzenarioVerwenden
Daten für eine Seite mit SSR oder Server-only-Zugriff laden+page.server.js mit load()
Einen API-Endpunkt für externe Nutzung bauen+server.js
Client-only-Daten nach der HydrationonMount + fetch

Für Seitendaten, die Serverzugriff, Secrets oder SSR benötigen, ist +page.server.js üblicherweise der richtige Standard. Es läuft serverseitig, hält Secrets vom Client fern und integriert sich sauber mit den Form Actions von SvelteKit für Progressive Enhancement.

Kleine praktische Erfolge

Keyed {#each}-Blöcke verhindern subtile DOM-Recycling-Bugs. Verwenden Sie immer eine stabile eindeutige ID als Key – niemals den Index.

$inspect.trace wird beim Debugging von Reaktivität zu selten genutzt. Setzen Sie es an den Anfang eines $effect oder $derived.by, um genau zu sehen, welche Dependency einen Re-Run ausgelöst hat.

Snippets statt Slots für wiederverwendbare Markup-Bausteine. Snippets lassen sich besser komponieren und können als Props übergeben werden, was Komponenten-APIs sauberer macht.

Vermeiden Sie Legacy-Syntax in neuem Code. Ersetzen Sie on:click durch onclick, <slot> durch {#snippet} und export let durch $props(). Diese Patterns entsprechen den modernen Svelte-5-Konventionen und dem aktuellen Compiler-Verhalten.

Fazit

Svelte 5 belohnt Zurückhaltung. Je präziser Sie Reaktivität scopen – $state nur dort, wo nötig, $derived statt $effect und Context statt Modul-Globals – desto vorhersagbarer und performanter wird Ihre Anwendung. Beginnen Sie mit dem einfachsten reaktiven Primitive, das das Problem löst, und greifen Sie nur dann zu mächtigeren Werkzeugen, wenn die einfacheren tatsächlich an ihre Grenzen stoßen.

FAQs

Verwenden Sie $state.raw, wenn Sie planen, den gesamten Wert zu ersetzen, anstatt Teile davon zu mutieren – etwa beim Speichern abgerufener API-Antworten oder großer Arrays, die Sie komplett neu zuweisen. Es überspringt den Overhead des reaktiven Proxys, was die Performance bei großen Datenmengen verbessert. Verwenden Sie einfaches $state, wenn Sie feingranulare Reaktivität für verschachtelte Mutationen benötigen, etwa zum Aktualisieren eines Elements innerhalb eines Arrays.

$derived ist deklarativ, verfolgt seine Dependencies automatisch und liefert einen Read-only-Wert, der synchron bleibt. $effect läuft imperativ als Side Effect und ist schwerer nachzuvollziehen, da es Timing-Bugs und unnötige Re-Runs einführen kann. Reservieren Sie $effect für die Synchronisation mit Systemen außerhalb von Sveltes Reaktivität, etwa Third-Party-Bibliotheken, Canvas-APIs oder manueller DOM-Arbeit.

Nicht in SSR-Umgebungen wie SvelteKit. Modul-globaler State wird über jeden Request hinweg geteilt, den der Server bearbeitet, wodurch Daten eines Nutzers in die Session eines anderen Nutzers leaken können. Verwenden Sie Sveltes Context-API mit setContext und getContext, idealerweise gestützt durch eine Klasse mit $state-Feldern. Dadurch wird der State pro Request und pro Komponenten-Baum gescoped, während Reaktivität und Typsicherheit erhalten bleiben.

Verwenden Sie +page.server.js, wenn die Daten zu einer bestimmten Seite gehören und von SSR, SEO, serverseitigem Zugriff oder Form Actions profitieren. Verwenden Sie +server.js, wenn Sie einen eigenständigen HTTP-Endpunkt benötigen, etwa eine JSON-API für externe Clients, Webhooks oder Fetch-Aufrufe außerhalb einer Seite. Wenn die Daten ausschließlich von einer Seite gerendert werden und serverseitige Fähigkeiten benötigen, ist +page.server.js üblicherweise der bessere Standard.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay