Svelteの遅延読み込みモジュール

コンポーネントをオンデマンドでインポートする方法

Svelteでの動的インポート

Svelteでコーディングする場合、実際に必要なときにオンデマンドでのみコンポーネントをロードする必要がある場合があります。 Reactは、その「サスペンス」コンポーネントを使用して、この問題を非常に巧みに解決しました。 Svelteで同様のことを達成したい場合は、良いニュースがあります。

サスペンスなしのSvelte「サスペンス」

基本的に必要なのは、Svelteの組み込みメカニズムを使用して、コンポーネント自体で非同期関数が呼び出されるのを待つことです。次の簡単な例は、私がそれが何を意味するかを示しています。

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

ご覧のとおり、関数の戻り値を待ってから、UIで使用します。モジュール全体のインポートにも同じ手法を使用できます。

Svelteによる動的インポート

ES6で利用可能な動的な「インポート」を使用して、単純な遅延コンポーネントのインポートを記述できます。

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

この知識に基づいて、任意のコンポーネントを遅延ロードできるようになりました。私が実際にspikze.clubに使用している実際の例は、特定のアイコンをオンデマンドでロードする単一の「アイコン」コンポーネントの実装です。

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

要約

ES6からの動的インポートを使用して、オンデマンドでデータを単純にインポートする方法を見てきました。これはコンポーネントとサードパーティライブラリの両方に当てはまるため、次のSvelteアプリのスケーリングを妨げるものは何もありません。