Svelte/SvelteKit: Dynamic import of components with variable
Asked Answered
S

3

5

I want to dynamically import components without importing a specific component. I want to set the component name with a variable, received from the store:

<script lang="ts">
    // SVELTE
    import { onMount } from 'svelte';

    // STORE
    import { dynamicComponent } from '$stores/dynamicTitle';


    $: $dynamicComponent;
    console.log($dynamicComponent)

    
    let renderDynamicComponent
    

    onMount(async () => {       
        const importValue = (await import(`../../lib/components/Home/DynamicComponents/${String($dynamicComponent)}.svelte`)).default;
        // const importValue = (await import(`../../lib/components/Home/DynamicComponents/IntroSectionCustom.svelte`)).default;
        renderDynamicComponent = importValue
    });

<svelte:component this={renderDynamicComponent}/>

But I get:

Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: http://localhost:3000/src/lib/components/Home/DynamicComponents/Intro-Section-Custom.svelte

I do not understand. From the error, it seems to be the right path ...

Sonasonant answered 23/9, 2021 at 7:14 Comment(0)
M
5

I don't think Svelte + the bundler currently support dynamically generated paths:

let thing = 'Thing';
Thing = (await import(`./${thing}.svelte`)).default; // this won't work
Thing = (await import(`./Thing.svelte`)).default; // this will work

limitation of the bundler.
github issue: https://github.com/sveltejs/svelte/issues/6702

Merrow answered 12/10, 2021 at 16:5 Comment(0)
A
3

The Rollup plugin @rollup/plugin-dynamic-import-vars might be of help here. I haven't used it with SvelteKit specifically, but it worked fine with standard Svelte with Vite as bundler.

// Example.svelte
function importLocale(locale) {
  return import(`./locales/${locale}.js`);
}
// vite.config.js
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';

export default (mode) =>
  defineConfig({
    plugins: [
      dynamicImportVars({
        include: './src/Example.svelte'
      })
    ]
});

SvelteKit uses Vite behind the scenes, but has its own configuration format. In svelte.config.js, pass dynamicImportVars() to the config.vite.plugins key:

// svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
  vite: {
    plugins: [
      dynamicImportVars({
        include: './src/Example.svelte'
      })
    ]
  }
};

export default config;

Please take note of the limitations mentioned in the README of the Rollup plugin.

Aquamanile answered 4/3, 2022 at 11:20 Comment(0)
S
0

What you're doing does work if not using import vars. When adding an import variable you need make your renderDynamicComponent identifier reactive. So instead of this:

let renderDynamicComponent

Do this:

$: renderDynamicComponent = null

This will allow svelte:component to render your imported component with dynamic path variable. This seems to be a special case when using dynamic import vars with Vite.

Shantae answered 10/5, 2022 at 11:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.