'How do I use dynamically loaded components with vue3?

I have been a happy user of httpVueLoader for a while, as it allowed me to use a fairly simple setup: libraries off CDN, a server serving components statically, and no compiling steps in the development process.

This is great for me as I do my backend stuff in another language and framework (perl + Mojolicious).

I also use single file components with the style/template/script structure, like this:

<style scoped>
</style>
<template>
  <div>empty component</div>
</template>
<script>
module.exports = {
    data: function () {
        return {
        };
    },
    async mounted(){
    },
    destroyed: function(){
    },
    methods: {
    },
    components: {
    },
}
</script>

As I try updating things to Vue3 I struggle to figure out a similar setup, and I got this far:

import 'https://threejs.org/build/three.js'
import 'https://threejs.org/examples/js/loaders/GLTFLoader.js'
import 'https://threejs.org/examples/js/controls/OrbitControls.js'

const { loadModule } = window['vue3-sfc-loader'];
const options = {
    moduleCache: { vue: Vue },
    async getFile(url) {
        console.log(url);
        const res = await fetch(url);
        if ( !res.ok )
            throw Object.assign(new Error(res.statusText + ' ' + url), { res });
        return {
            getContentData: asBinary => asBinary ? res.arrayBuffer() : res.text(),
        }
    },
    addStyle(textContent) {
        const style = Object.assign(document.createElement('style'), { textContent });
        const ref = document.head.getElementsByTagName('style')[0] || null;
        document.head.insertBefore(style, ref);
    },    
}

var router = VueRouter.createRouter({
    history: VueRouter.createWebHistory('/v3/app/'),
    routes: [
        { path: '/',       component: Vue.defineAsyncComponent( () => loadModule('/components/index.vue', options) ) },
        { path: '/three',  component: Vue.defineAsyncComponent( () => loadModule('/components/three.vue', options) ) },
        ],
});

Vue.createApp({
    router: router,
    data(){
        return {
        }
    },
    async mounted(){
    },
    methods: {
    },
    components: {
    },
    filters: {
    }    
})
    .use(router)
    .mount('#app')

However:

  • this loads the index.vue component ok, but does not seem to recognize the path at /three and does not load the component at all (no trace of an attempt failing with 404 either). Why is that?
  • I don't get what I should do given that I might mount the app at a different point later - should that be updated with the app's root every time?

I realize my practices might not be perfect or perfectly up-to-date, but they seem a decent compromise given that this is not my day job, and it used to get things done ok - until I tried to switch to Vue3 (something which I would like to be doing).



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source