0

Here is a simple Vue component it will dynamically load separate .vue files based on which component is selected :

<script setup> import {computed, defineAsyncComponent, ref, watch} from "vue"; import Loading from "@/components/Loading.vue"; import Missing from "@/components/Missing.vue"; import {TwSelect,TwButton} from "vue3-tailwind-components"; const componentList = [ {label:"One",value:'one.vue'}, {label:"Two",value:'two.vue'}, {label:"Three",value:'three.vue'}, ] const dynamicComponent = ref('') function loadComponent(component) { return defineAsyncComponent({ loader: () => import( /* @vite-ignore */component), loadingComponent:Loading, delay:2000, errorComponent: Missing, timeout: 3000 }) } const is_selected = computed(()=>{ return dynamicComponent.value.length>0; }) const component_with_path = computed(()=>{ return './dynamic/'+dynamicComponent.value }) </script> <template> <h2 class="text-2xl">This is the static loader</h2> <p>It loads up a dynamic Vue component using defineAsyncComponent</p> <tw-select :items="componentList" v-model="dynamicComponent"></tw-select> <component v-if="is_selected" :is="loadComponent(component_with_path)"></component> </template> 

When I run in dev mode the component_with_path is resolved and the dynamic component loads. How do I configure Vite to build so that the path of the dynamic components are resolved the same way?

please feel free to clone https://github.com/richardhulbert/vite-async.git to see the issue.

0

3 Answers 3

0

I'm not sure if this is what you mean, but the configuration in vite could look like this:

export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, build: { rollupOptions: { output: { manualChunks(id) { if (id.includes('dynamic')) { return 'dynamic-components'; } }, }, }, }, }); 

or just check this out: https://www.npmjs.com/package/vite-plugin-dynamic-import

Sign up to request clarification or add additional context in comments.

Comments

0

To describe your problem more accurately, you are using a relative path like this:

 //return a string const component_with_path = computed(()=>{ return './dynamic/'+dynamicComponent.value }) //... loadComponent(component_with_path) 

Since componentWithPath is a string, Vite does not treat it as a module path and does not process it correctly (both in development and build modes).

try:

import { defineAsyncComponent } from 'vue' const dynamicComponent = defineAsyncComponent(() => import(componentWithPath.value)) //in template <component :is="dynamicComponent" /> 

using import vite will adjuste the path

2 Comments

Isn't that what I am doing? loader: () => import( component),
I can see that Vite does indeed resolve the path and load in the module however in build it doesn't
0

Thanks to gitsal who gave me a good clue!

"Since componentWithPath is a string, Vite does not treat it as a module path and does not process it correctly"

So needed to make a file let's call it componentMapping

export const componentMapping = { 'one.vue':()=>import('./components/dynamic/one.vue'), 'two.vue':()=>import('./components/dynamic/two.vue'), 'three.vue':()=>import('./components/dynamic/three.vue') } 

I will figure out a way to create this perhaps using import.meta.glob('./components/dynamic/*.vue' )

Then I import this into Loader.vue and change the function to:

function loadComponent(component) { const loader = componentMapping[component]; if (!loader) { return Missing; } return defineAsyncComponent({ loader, loadingComponent:Loading, delay:2000, errorComponent: Missing, timeout: 3000 }) } 

Lastly I only pass the Vue component name (not the path) to the loadComponent function.

What really confused me is that the above code worked when Vite was in dev mode. Now it works in build as well!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.