Back

Wie man Komponenten in Svelte Lazy Loading anwendet

Wie man Komponenten in Svelte Lazy Loading anwendet

Ihre Svelte-App mag standardmäßig schnell sein, aber wenn Sie einen Rich-Text-Editor, eine Chart-Bibliothek oder ein komplexes Dashboard-Widget in Ihr initiales JavaScript-Payload bündeln, laden Benutzer Code herunter, den sie möglicherweise nie verwenden. Lazy Loading auf Komponentenebene in Svelte behebt dies, indem diese schweren Imports erst dann geladen werden, wenn sie tatsächlich benötigt werden.

Im Gegensatz zu React verfügt Svelte über keinen eingebauten lazy()-Helper. Stattdessen basiert Lazy Loading direkt auf der nativen import()-Funktion von JavaScript in Kombination mit bedingtem Rendering. Es ist manueller, aber auch flexibler.

Wichtigste Erkenntnisse

  • Svelte verfügt über keinen eingebauten lazy()-Helper, daher verwendet Lazy Loading die native import()-Funktion von JavaScript mit bedingtem Rendering
  • SvelteKit übernimmt automatisch das Code-Splitting auf Routen-Ebene, aber Lazy Loading auf Komponentenebene ist weiterhin für schwere Widgets innerhalb einer einzelnen Seite notwendig
  • Vite teilt dynamische Imports ohne jegliche Konfiguration in separate Chunks auf
  • Drei Kernmuster decken die meisten Anwendungsfälle ab: Laden bei Bedarf mit {#await}, Vorladen beim Hovern und verzögertes Laden, wenn der Browser im Leerlauf ist

Warum Lazy Loading auf Komponentenebene in SvelteKit weiterhin wichtig ist

SvelteKit übernimmt bereits automatisch das Code-Splitting auf Routen-Ebene. Jede Route erhält ihren eigenen Chunk, sodass die Navigation zwischen Seiten das initiale Bundle nicht aufbläht. Aber innerhalb einer einzelnen Seite wird alles, was Sie am Anfang einer .svelte-Datei importieren, zusammen gebündelt und vorab geladen.

Hier wird Lazy Loading auf Komponentenebene wertvoll. Wenn eine Seite eine schwere Chart-Komponente, einen Video-Player oder ein Modal enthält, das erst nach Benutzerinteraktion erscheint, gibt es keinen Grund, diesen Code beim Seitenaufruf zu laden.

SvelteKit baut mit Vite, das dynamische Imports nativ verarbeitet. Wenn Vite import('./HeavyChart.svelte') sieht, teilt es dieses Modul automatisch in einen separaten Chunk auf. Keine zusätzliche Konfiguration erforderlich.

Wie man Svelte-Komponenten Lazy Loading anwendet: Kernmuster

Grundlegendes Lazy Loading mit {#await}

Der einfachste Ansatz verwendet Sveltes {#await}-Block direkt im Template:

<!-- src/routes/+page.svelte -->
<script>
  let showChart = false;
  let chartData = [1, 2, 3];
</script>

<button onclick={() => showChart = true}>Load Chart</button>

{#if showChart}
  {#await import('$lib/components/HeavyChart.svelte')}
    <p>Loading chart...</p>
  {:then Chart}
    <Chart.default data={chartData} />
  {:catch error}
    <p>Failed to load chart: {error.message}</p>
  {/await}
{/if}

Dies funktioniert sowohl in Svelte 4 als auch in Svelte 5. Der {:catch}-Block ist wichtig — Netzwerkfehler passieren, und stille Fehler machen das Debugging schmerzhaft. In Svelte 4 verwendet man typischerweise <svelte:component this={Component}> für dynamisches Wechseln von Komponenten. In modernem Svelte kann das Ändern der Komponentenreferenz auch direkt ein erneutes Rendering auslösen.

Der Browser cached das Modul nach dem ersten Import. Nachfolgende Renderings derselben Komponente lösen keine neue Netzwerkanfrage aus.

Laden beim Hovern für schnellere wahrgenommene Performance

Ein gängiges Muster ist es, mit dem Laden zu beginnen, wenn der Benutzer Absicht signalisiert — beim Hovern über ein Auslöserelement:

<!-- src/routes/+page.svelte -->
<script lang="ts">
  import type { Component } from 'svelte';

  let HeavyWidget: Component<{ message: string }> | null = $state(null);

  async function loadWidget() {
    if (!HeavyWidget) {
      const module = await import('$lib/components/HeavyWidget.svelte');
      HeavyWidget = module.default;
    }
  }
</script>

<div onmouseenter={loadWidget}>
  <p>Hover to preload the widget</p>
</div>

{#if HeavyWidget}
  <HeavyWidget message="Ready!" />
{/if}

Dies funktioniert gut für Tooltips, Popovers und Sidebars. Die Komponente beginnt zu laden, bevor der Benutzer klickt, sodass sie zum Zeitpunkt der Interaktion oft bereits gecached ist.

Laden, wenn der Browser im Leerlauf ist

Für nicht-kritische Komponenten, die die Seite verbessern, aber nicht sofort benötigt werden, verwenden Sie requestIdleCallback:

<script lang="ts">
  import { onMount } from 'svelte';
  import type { Component } from 'svelte';

  let FeedbackWidget: Component | null = $state(null);

  onMount(() => {
    const load = () =>
      import('$lib/components/FeedbackWidget.svelte').then(
        (m) => (FeedbackWidget = m.default)
      );

    if ('requestIdleCallback' in window) {
      requestIdleCallback(load);
    } else {
      setTimeout(load, 300); // Fallback für Safari
    }
  });
</script>

{#if FeedbackWidget}
  <FeedbackWidget />
{/if}

Beachten Sie, dass die Safari-Unterstützung für requestIdleCallback historisch inkonsistent war, daher wird der setTimeout-Fallback empfohlen.

Wann man kein Lazy Loading verwenden sollte

Nicht jede Komponente profitiert von Lazy Loading. Vermeiden Sie es für:

  • Above-the-fold UI — Navigation, Hero-Bereiche, primärer Inhalt
  • Kleine Komponenten — der asynchrone Overhead überwiegt die Einsparungen
  • Komponenten, die sofort beim Mount benötigt werden — das Lade-Flackern verschlechtert die UX

Übermäßiges Aufteilen erzeugt viele kleine asynchrone Chunks. Moderne Bundler wie Vite handhaben dies effizient, aber es gibt dennoch einen Punkt abnehmender Erträge.

Fazit

Lazy Loading von Svelte-Komponenten läuft auf eines hinaus: import() anstelle eines statischen Imports zu verwenden und dann das Ergebnis bedingt zu rendern. Der Vite-basierte Build von SvelteKit übernimmt das Code-Splitting automatisch. Die drei oben genannten Muster — bei Bedarf, beim Hovern und im Leerlauf — decken die meisten realen Szenarien ab. Wählen Sie den Auslöser, der dem Zeitpunkt entspricht, zu dem Benutzer die Komponente tatsächlich benötigen, fügen Sie Fehlerbehandlung hinzu, und Ihr initiales Bundle bleibt schlank.

FAQs

Dynamischer Import funktioniert in beiden Versionen. In Svelte 4 rendern Sie die geladene Komponente typischerweise mit svelte:component und dem this-Attribut. In Svelte 5 können Sie die aufgelöste Komponente direkt als Tag im Template verwenden. Der zugrunde liegende Import-Mechanismus ist in beiden Fällen derselbe.

Dynamische Imports werden auch während des SSR ausgeführt, da Node.js sie unterstützt. Lazy Loading ist jedoch primär eine clientseitige Optimierung, die darauf abzielt, das initiale JavaScript-Payload des Browsers zu reduzieren. Wenn eine Komponente aus SEO- oder First-Paint-Gründen auf dem Server gerendert werden muss, ist ein statischer Import die bessere Wahl.

Überprüfen Sie Ihre Build-Ausgabe oder verwenden Sie einen Bundle-Analyzer, um große Chunks zu identifizieren. Komponenten, die schwere Drittanbieter-Bibliotheken wie Chart-Renderer, Rich-Text-Editoren oder Map-Widgets einbinden, sind starke Kandidaten. Wenn eine Komponente weniger als ein paar Kilobytes hinzufügt, überwiegt der Overhead einer zusätzlichen Netzwerkanfrage wahrscheinlich die Einsparungen.

Nein. Der Browser cached das Modul, nachdem der erste dynamische Import aufgelöst wurde. Bei nachfolgenden Renderings wird das gecachte Modul sofort zurückgegeben, sodass der Ladezustand nur beim initialen Abruf erscheint. Sie können das Modul auch beim Hovern oder während der Leerlaufzeit vorladen, um die sichtbare Verzögerung vollständig zu eliminieren.

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