Modules de chargement paresseux dans Svelte

Comment importer votre composant à la demande

Importation dynamique dans Svelte

Lors du codage dans Svelte, vous devrez peut-être uniquement charger des composants à la demande, lorsqu'ils sont réellement nécessaires. React a résolu ce problème de manière magistrale avec son composant "Suspense". Si vous souhaitez réaliser quelque chose de similaire dans Svelte, j'ai de bonnes nouvelles pour vous.

Svelte "Suspense" sans suspense

Fondamentalement, ce qui est requis est d'utiliser le mécanisme intégré de Svelte pour attendre les appels de fonction asynchrones dans le composant lui-même. L'exemple simple suivant montre ce que je veux dire par là.

<script>
  // Dummy function, just so that we
  // have some async stuff.
	async function getData() {
		await new Promise(res => setTimeout(res, 1000));
		return { key: "value" };
	}
</script>

{#await getData()}
	<p>Fetching data...</p>
{:then res}
	<p>Accessing data: "key": "{res.key}"</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}

Comme vous pouvez le voir, nous attendons simplement la valeur de retour de la fonction, puis nous l'utilisons dans notre interface utilisateur. La même technique peut être utilisée pour importer des modules entiers.

Importation dynamique avec Svelte

En utilisant "l'importation" dynamique, disponible dans ES6, nous pouvons écrire une simple importation de composants paresseux.

//
// Live demo:
// https://svelte.dev/repl/b7551180977d4e738b07d428f3172d5e?version=3.46.4
//

//
// App.svelte
// 

<h1>App title</h1>

{#await import("./Content.svelte") then Module}
	<Module.default subtitle="Subtilte as prop" />
{/await}
//
// Content.svelte
//

<script>
	export let subtitle;
</script>

<article>
  <h2>
		Content title
	</h2>
	<h3>
		{subtitle}
	</h3>
	<p>
		Content body.
	</p>
</article>

Forts de ces connaissances, nous sommes désormais en mesure de charger paresseusement n'importe quel composant. Un exemple pratique que j'utilise actuellement pour spikze.club est la mise en œuvre d'un seul composant "Icon" qui charge l'icône spécifique à la demande.

<!--
  Source: https://carbon-icons-svelte.onrender.com/
-->
<script lang="ts">
  // Using a link so that 'clsx' can eliminate
  // all other variant compared to an enum, which
  // should lead to a smaller size at runtime.
  export let variant: "internal-link" | "external-link" | "section-link" | "close" | "add-circle";
  let cn: string = undefined;
  export { cn as class };
</script>

{#if variant === "external-link"}
  {#await import("carbon-icons-svelte/lib/ArrowUpRight20") then Icon}
    <Icon.default class={cn} />
  {/await}
{/if}

{#if variant === "internal-link"}
  {#await import("carbon-icons-svelte/lib/ArrowRight20") then Icon}
    <Icon.default class={cn} />
  {/await}
{/if}

{#if variant === "section-link"}
  {#await import("carbon-icons-svelte/lib/ArrowDown20") then Icon}
    <Icon.default class={cn} />
  {/await}
{/if}

{#if variant === "close"}
  {#await import("carbon-icons-svelte/lib/Close20") then Icon}
    <Icon.default class={cn} />
  {/await}
{/if}

{#if variant === "add-circle"}
  {#await import("carbon-icons-svelte/lib/AddAlt20") then Icon}
    <Icon.default class={cn} />
  {/await}
{/if}

Emballer

Vous avez vu comment utiliser l'importation dynamique depuis ES6 pour importer simplement des données à la demande. Comme cela s'applique à la fois à vos composants et aux bibliothèques tierces, rien ne vous empêche de faire évoluer votre prochaine application Svelte.