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