onMount ist die wahrscheinlich bekannteste Lifecycle-Funktion in Svelte. Sie führt eine Funktion aus, sobald deine Komponente fertig im DOM gelandet ist — also nach dem ersten Render. Typische Aufgaben: einen Drittanbieter-Initialisieren (Chart, Karte, Editor), eine API abfragen, einen Timer starten oder etwas im echten DOM messen. Dieser Artikel erklärt, wie onMount funktioniert, was beim Server-Side-Rendering passiert, wie Cleanup geht — und wann du in Svelte 5 stattdessen besser $effect nimmst.
Was ist onMount?
Stell dir vor, deine Komponente wird das erste Mal angezeigt. Svelte baut das HTML, hängt es ins DOM, der Browser zeichnet es. Genau in dem Moment, wenn alles fertig ist und der Nutzer die Komponente sehen kann, läuft onMount.
<script>
import { onMount } from 'svelte';
onMount(() => {
console.log('Komponente ist jetzt im DOM');
});
</script>
<h1>Hallo</h1>Wichtig zu verstehen:
onMountist eine Funktion, die du aus demsvelte-Modul importierst.- Du übergibst ihr eine Callback-Funktion, die später laufen soll.
- Der Aufruf von
onMount(...)selbst muss im Top-Level des<script>stehen — nicht in einerif- odersetTimeout-Anweisung.
Wann genau läuft onMount?
Der Zeitpunkt ist wichtig, weil viele Probleme daher kommen, dass man ihn missversteht:
- Nach dem ersten Render im Browser.
- Nicht beim Server-Side-Rendering (SSR). Wenn deine Seite per SvelteKit auf dem Server gerendert wird, läuft
onMountdort nicht. Erst im Browser, nach Hydration. - Nur einmal pro Komponenten-Instanz. Wenn die Komponente unmounted und später wieder gemountet wird, läuft sie erneut — aber nicht bei normalen Updates.
Das macht onMount ideal für Aufgaben, die das echte DOM brauchen oder nur einmalig passieren sollen.
Cleanup mit der Rückgabefunktion
Wenn dein onMount etwas startet, was später beendet werden muss — z. B. einen Timer, einen Listener, eine WebSocket-Verbindung — dann gibst du eine Funktion zurück. Svelte führt sie aus, wenn die Komponente entfernt wird.
<script>
import { onMount } from 'svelte';
let seconds = $state(0);
onMount(() => {
const intervalId = setInterval(() => {
seconds++;
}, 1000);
// Cleanup: läuft beim Unmount
return () => clearInterval(intervalId);
});
</script>
<p>Sekunden seit Mount: {seconds}</p>So entsteht keine „Memory-Leak”-Situation, in der ein Timer im Hintergrund weiterläuft, obwohl die Komponente längst weg ist.
async in onMount?
onMount kann eine async-Funktion sein:
<script>
import { onMount } from 'svelte';
let user = $state(null);
onMount(async () => {
const res = await fetch('/api/user');
user = await res.json();
});
</script>
{#if user}
<h1>{user.name}</h1>
{:else}
<p>Lädt …</p>
{/if}Aber Achtung: Bei einer async-Funktion kannst du keine Cleanup-Funktion zurückgeben. Eine async-Funktion gibt immer ein Promise zurück, nicht eine Funktion. Wenn du Cleanup brauchst, geh so vor:
<script>
import { onMount } from 'svelte';
let user = $state(null);
onMount(() => {
let cancelled = false;
async function load() {
const res = await fetch('/api/user');
if (!cancelled) user = await res.json();
}
load();
return () => { cancelled = true; };
});
</script>Erklärung: Die äußere Funktion ist synchron (gibt Cleanup zurück), die innere load-Funktion erledigt das Asynchrone. Die cancelled-Flag verhindert, dass ein verzögertes fetch-Ergebnis noch in eine bereits unmountete Komponente schreibt.
Praxis-Beispiel: Drittanbieter initialisieren
Klassiker — eine Chart-Library, die das Element zur Laufzeit braucht:
<script>
import { onMount } from 'svelte';
import { Chart } from 'chart.js/auto';
let { data } = $props();
let canvas;
let chartInstance;
onMount(() => {
chartInstance = new Chart(canvas, {
type: 'bar',
data,
});
return () => chartInstance.destroy();
});
</script>
<canvas bind:this={canvas}></canvas>Schritt für Schritt:
bind:this={canvas}gibt uns die Referenz auf das<canvas>-Element.onMountläuft erst, wenn das<canvas>wirklich im DOM hängt — vorher ist der Zugriff sinnlos.- Beim Unmount zerstören wir die Chart-Instanz, damit keine Listener oder Animation-Frames im Hintergrund weiterlaufen.
onMount vs. $effect – wann nimmt man was?
In Svelte 5 mit Runes gibt es eine zweite Möglichkeit für „nach dem Mount”: die Rune $effect (siehe $effect). Beide laufen nach dem ersten Render — die Unterschiede liegen in der Wiederholung und im Tracking.
| Aspekt | onMount | $effect |
|---|---|---|
| Wie oft? | Genau einmal pro Mount | Bei jeder Änderung der Abhängigkeiten |
| Reagiert auf $state? | Nein | Ja (automatisches Tracking) |
| Cleanup | return () => … | return () => … |
| Im SSR? | Nein | Nein |
Faustregel:
- „Nur einmal beim Start” ->
onMount. - „Reagieren, wenn ein Wert sich ändert” ->
$effect.
Beide haben ihren Platz — onMount ist klarer, wenn die Initialisierung wirklich nur einmal passieren soll.
Häufige Stolperfallen
onMount in einer Bedingung aufrufen.
<script>
import { onMount } from 'svelte';
let { active } = $props();
if (active) {
onMount(() => { /* … */ }); // läuft nicht zuverlässig
}
</script>Lifecycle-Hooks müssen im Top-Level des <script> stehen. Bedingte Logik gehört innen in den Callback.
onMount mit Cleanup als async vergessen.
Wer onMount(async () => { … return () => …; }) schreibt, hat keine Cleanup-Funktion zurückgegeben — sondern ein Promise, das eine Funktion enthält. Cleanup feuert nicht. Lösung: Die äußere Funktion synchron lassen (siehe Abschnitt 04).
Annahme: Läuft auch beim Server-Rendering.
Tut es nicht. Wer im SSR-Kontext etwas tun will, nutzt SvelteKit-load-Funktionen oder andere Hooks.
document oder window außerhalb von onMount nutzen.
Im Top-Level des Scripts greift dein Code beim SSR auch auf dem Server — wo window und document nicht existieren. Solche Zugriffe gehören in onMount.
<script>
const width = window.innerWidth; // crasht auf dem Server
</script><script>
import { onMount } from 'svelte';
let width = $state(0);
onMount(() => {
width = window.innerWidth;
});
</script>