Módulos de carga diferida en Svelte

Cómo importar su componente bajo demanda

Importación dinámica en Svelte

Al codificar en Svelte, es posible que tenga el requisito de cargar solo componentes a pedido, cuando realmente se necesitan. React ha resuelto este problema de manera bastante magistral con su componente "Suspenso". Si quieres lograr algo similar en Svelte, te tengo buenas noticias.

Esbelta "Suspenso" sin suspenso

Básicamente, lo que se requiere es usar el mecanismo integrado de Svelte para esperar llamadas de funciones asíncronas en el propio componente. El siguiente ejemplo simple muestra lo que quiero decir con eso.

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

Como puede ver, simplemente esperamos el valor de retorno de la función y luego lo usamos en nuestra interfaz de usuario. La misma técnica se puede utilizar para importar módulos completos.

Importación dinámica con Svelte

Usando la "importación" dinámica, disponible en ES6, podemos escribir una importación de componente perezoso simple.

//
// 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>

Sobre la base de este conocimiento, ahora podemos cargar de forma diferida cualquier componente. Un ejemplo práctico que estoy usando para spikze.club es la implementación de un solo componente de "Icono" que carga el ícono específico a pedido.

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

Envolver

Ha visto cómo usar la importación dinámica de ES6 para importar simplemente cualquier dato bajo demanda. Como esto se aplica tanto a sus componentes como a las bibliotecas de terceros, no hay nada que le impida escalar su próxima aplicación Svelte.