Search code examples
sveltesapper

Sapper/Svelte possible to conditionally import components?


In Sapper I am trying to import a component only if being rendered client side (using onMount). Is there something similar to React Suspense and React.lazy? Or is there another approach?


Solution

  • You can certainly do it that way, yes:

    <script>
      import { onMount } from 'svelte';
        
      let Thing;
        
      onMount(async () => {
        Thing = (await import('./Thing.svelte')).default;
      });
    </script>
    
    <svelte:component this={Thing} answer={42}>
      <p>some slotted content</p>
    </svelte:component>
    

    Demo here.

    Alternatively, you could wrap that into a component:

    <!-- Loader.svelte -->
    <script>
      import { onMount } from 'svelte';
        
      let loader;
      let Component;
        
      onMount(async () => {
        Component = (await loader()).default;
      });
        
      export { loader as this };
    </script>
    
    <svelte:component this={Component} {...$$restProps}>
      <slot></slot>
    </svelte:component>
    
    {#if !Component}
      <slot name="fallback"></slot>
    {/if}
    
    <Loader
      this={() => import('./Thing.svelte')}
      answer={42}
    >
      <p>some slotted content</p>
      <p slot="fallback">loading...</p>
    </Loader>
    

    Demo here. A caveat with this approach is that slots other than default won't be 'forwarded' to the underlying component.