Back

Comment Lazy Loader des Composants dans Svelte

Comment Lazy Loader des Composants dans Svelte

Votre application Svelte est peut-être rapide par défaut, mais si vous intégrez un éditeur de texte riche, une bibliothèque de graphiques ou un widget de tableau de bord complexe dans votre payload JavaScript initial, les utilisateurs téléchargent du code qu’ils n’utiliseront peut-être jamais. Le lazy loading au niveau des composants dans Svelte résout ce problème en différant ces imports lourds jusqu’à ce qu’ils soient réellement nécessaires.

Contrairement à React, Svelte ne dispose pas d’un helper lazy() intégré. Au lieu de cela, le lazy loading repose directement sur la fonction native import() de JavaScript combinée au rendu conditionnel. C’est plus manuel, mais aussi plus flexible.

Points Clés

  • Svelte ne dispose pas d’un helper lazy() intégré, donc le lazy loading utilise la fonction native import() de JavaScript avec le rendu conditionnel
  • SvelteKit gère automatiquement le code splitting au niveau des routes, mais le lazy loading au niveau des composants reste nécessaire pour les widgets lourds au sein d’une même page
  • Vite divise les imports dynamiques en chunks séparés sans aucune configuration
  • Trois patterns principaux couvrent la plupart des cas d’usage : chargement à la demande avec {#await}, préchargement au survol, et différé jusqu’à ce que le navigateur soit inactif

Pourquoi le Lazy Loading au Niveau des Composants Reste Important dans SvelteKit

SvelteKit gère déjà automatiquement le code splitting au niveau des routes. Chaque route obtient son propre chunk, donc naviguer entre les pages n’alourdit pas le bundle initial. Mais au sein d’une même page, tout ce que vous importez en haut d’un fichier .svelte est regroupé et chargé d’emblée.

C’est là que le lazy loading au niveau des composants devient précieux. Si une page contient un composant de graphique lourd, un lecteur vidéo ou une modale qui n’apparaît qu’après une interaction utilisateur, il n’y a aucune raison de charger ce code dès l’arrivée sur la page.

SvelteKit se construit avec Vite, qui gère nativement les imports dynamiques. Lorsque Vite rencontre import('./HeavyChart.svelte'), il divise automatiquement ce module en un chunk séparé. Aucune configuration supplémentaire n’est nécessaire.

Comment Lazy Loader des Composants Svelte : Patterns Principaux

Lazy Loading Basique avec {#await}

L’approche la plus simple utilise le bloc {#await} de Svelte directement dans le 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}

Cela fonctionne à la fois dans Svelte 4 et Svelte 5. Le bloc {:catch} est important — les échecs réseau arrivent, et les erreurs silencieuses rendent le débogage pénible. Dans Svelte 4, changer dynamiquement de composants utilise généralement <svelte:component this={Component}>. Dans Svelte moderne, changer la référence du composant peut également déclencher directement le re-rendu.

Le navigateur met en cache le module après le premier import. Les rendus ultérieurs du même composant ne déclenchent pas de nouvelle requête réseau.

Chargement au Survol pour une Meilleure Performance Perçue

Un pattern courant consiste à commencer le chargement lorsque l’utilisateur signale son intention — en survolant un élément déclencheur :

<!-- 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}

Cela fonctionne bien pour les tooltips, les popovers et les barres latérales. Le composant commence à se charger avant que l’utilisateur ne clique, donc au moment où il interagit, il est souvent déjà en cache.

Chargement Lorsque le Navigateur Est Inactif

Pour les composants non critiques qui améliorent la page mais ne sont pas immédiatement nécessaires, utilisez 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 pour Safari
    }
  });
</script>

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

Notez que le support de requestIdleCallback par Safari a historiquement été incohérent, donc le fallback setTimeout est recommandé.

Quand Ne Pas Utiliser le Lazy Loading

Tous les composants ne bénéficient pas du lazy loading. Évitez-le pour :

  • L’UI au-dessus de la ligne de flottaison — navigation, sections hero, contenu principal
  • Les petits composants — la surcharge asynchrone dépasse les économies
  • Les composants nécessaires immédiatement au montage — le flash de chargement dégrade l’UX

Un découpage excessif crée de nombreux petits chunks asynchrones. Les bundlers modernes comme Vite gèrent cela efficacement, mais il existe toujours un point de rendements décroissants.

Conclusion

Le lazy loading des composants Svelte se résume à une chose : utiliser import() au lieu d’un import statique, puis rendre le résultat de manière conditionnelle. Le build basé sur Vite de SvelteKit gère automatiquement le code splitting. Les trois patterns ci-dessus — à la demande, au survol et en mode inactif — couvrent la plupart des scénarios réels. Choisissez le déclencheur qui correspond au moment où les utilisateurs ont réellement besoin du composant, ajoutez la gestion des erreurs, et votre bundle initial reste léger.

FAQ

L'import dynamique fonctionne dans les deux versions. Dans Svelte 4, vous rendez généralement le composant chargé en utilisant svelte:component avec l'attribut this. Dans Svelte 5, vous pouvez utiliser le composant résolu directement comme balise dans le template. Le mécanisme d'import sous-jacent est le même dans les deux cas.

Les imports dynamiques s'exécutent également pendant le SSR, puisque Node.js les supporte. Cependant, le lazy loading est principalement une optimisation côté client visant à réduire le payload JavaScript initial du navigateur. Si un composant doit être rendu sur le serveur pour des raisons de SEO ou de premier affichage, un import statique est le meilleur choix.

Vérifiez la sortie de votre build ou utilisez un analyseur de bundle pour identifier les chunks volumineux. Les composants qui intègrent de lourdes bibliothèques tierces comme des moteurs de rendu de graphiques, des éditeurs de texte riche ou des widgets de carte sont de bons candidats. Si un composant ajoute moins de quelques kilo-octets, la surcharge d'une requête réseau supplémentaire dépasse probablement les économies.

Non. Le navigateur met en cache le module après la résolution du premier import dynamique. Lors des rendus ultérieurs, le module en cache est retourné immédiatement, donc l'état de chargement n'apparaît que lors de la première récupération. Vous pouvez également précharger le module au survol ou pendant le temps d'inactivité pour éliminer complètement le délai visible.

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