Is there a way to defer the loading of dynamic imports in a Sapper route?

2k views Asked by At

I have a component that is fairly heavy on the home page of a project I'm working on. It includes the Three.js library and several utilities but it's only shown once an action triggered by a user occurs. There's no need to include it in the initial download because it just adds unnecessary weight to initial load and increases load time.

<script>
    let optionSelected = false;

    const imports = {
        component: () => import('./components/Component.svelte'),
    };
</script>

<button on:click|preventDefault={() => optionSelected = true}>
    Option Button
</button>

{#if optionSelected}
    {#await imports['component']() then module}
        <svelte:component this="{module.default}" />
    {/await}
{/if}

enter image description here

I'm using the dynamic import to force the heavy component into its on file to reduce the home page file size. I was hoping that the dynamic import would also defer the loading until the condition is met but that's not the case.

I've seen several examples of how to include a dynamic import in the onMount lifecycle function to bypass SSR but that does not yield the desired result. The component is still being included in the initial payload before it's needed.

<script>
    import { onMount } from 'svelte';

    let Component;
    let optionSelected = false;

    onMount(async () => {
        const comp = await import('./../components/Component.svelte');

        Component = comp.default;
    });
</script>

<button on:click|preventDefault={() => optionSelected = true}>
    Option Button
</button>

{#if optionSelected}
    <svelte:component this="{Component}" />
{/if}

Sapper/Svelte possible to conditionally import components?
Making a component SSR compatible

Is there a way to fetch the component after the initial page load similar to how preloaded routes are included with the service worker?

1

There are 1 answers

1
DougA On

The module gets imported whenever import is called. Since import is called onMount() it'll be loaded whenever the component mounts, instead of when the click happens.

Move your import call to a click handler, it'll only be loaded when the click is handled:

<script>

    let Component;
    let optionSelected = false;

    const handleClick = async () => {
      const foo= await import("./../components/Foo.svelte");
      Component = foo.default;
      optionSelected = true;
    };

</script>

<button on:click|preventDefault={handleClick}>
    Option Button
</button>

{#if optionSelected}
    <svelte:component this="{Component}" />
{/if}

Remember to enable code splitting in your javascript bundler, which it appears you've done.

enter image description here