I am building module vue.js app that is composed from different Vite/Vue projects.
The workflow – to have Theme plugin / **Menu **plugin which can be dynamically applied within vue app.
The components renders at the root level of the app, but it fails to render when nested.
(Theme component renders Menu component), however it appears in DOM as just component name….
I have tried to create separate vite/vue apps, build them, and then manually load them within index.html.
ThemePlugin project
- theme/vite.config.ts
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
build: {
rollupOptions: {
output: {
dir: "./dist",
entryFileNames: "plugin.js",
assetFileNames: "plugin.css",
chunkFileNames: "chunk.js",
manualChunks: undefined,
},
},
},
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
- theme/ThemeWrapper.vue
<template>
<div class="vite-theme-plugin-build">
<MenuLauncher></MenuLauncher>
<div style="color:red" v-if="test1">Is Rendered from Theme Wrapper</div>
</div>
</template>
<script lang="ts">
import type { App, Component } from 'vue';
type Framework = {
app: App;
externalComponents: {
ThemeWrapper: Component;
MenuLauncher: Component;
};
};
const w = window as unknown as Framework;
console.log(w);
export default {
name: "ThemeWrapper",
components: {
MenuLauncher: w.externalComponents.MenuLauncher
},
setup() {
return {
test1: true,
};
},
};
</script>
- theme/main.ts
import type { App, Component } from "vue";
import ThemeWrapperVue from "./ThemeWrapper.vue";
type Framework = {
app: App;
externalComponents: {
ThemeWrapper: Component;
MenuLauncher: Component;
};
};
const w = window as unknown as Framework;
w.externalComponents = w.externalComponents || {};
w.externalComponents.ThemeWrapper = ThemeWrapperVue;
MenuPlugin project
- menu/vite.config.ts
Identical to the ThemePlugin project configuration
- menu/MenuLauncher.vue
<template>
<div class="vite-menu-plugin-build">
<div>
This is dynamic menu launcher!
</div>
<div style="color:blue" v-if="test1">Is Rendered from MenuLauncher</div>
</div>
</template>
<script lang="ts">
export default {
name: "MenuLauncher",
setup() {
return {
test1: true,
};
},
};
</script>
- menu/main.ts
import type { App, Component } from "vue";
import MenuLauncherVue from "./MenuLauncher.vue";
type Framework = {
app: App;
externalComponents: {
ThemeWrapper: Component;
MenuLauncher: Component;
};
};
const w = window as unknown as Framework;
w.externalComponents = w.externalComponents || {};
w.externalComponents.MenuLauncher = MenuLauncherVue;
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="./menu/dist/plugin.js"></script>
<script src="./theme/dist/plugin.js"></script>
</head>
<body>
<div id="app"></div>
<script>
document.addEventListener("DOMContentLoaded", (event) => {
window.app = Vue.createApp({
setup() {
return {};
},
template: `
<div>
<div style="border: 1px solid gainsboro; margin:1rem;">
<div>ThemeWrapper component doesn't load MenuLauncher component....</div>
<ThemeWrapper></ThemeWrapper>
</div>
<div style="border: 1px solid gainsboro; margin:1rem;">
<div>Root component is able to render MenuLauncher... But above "ThemeWrapper" component cannot render it Why???</div>
<MenuLauncher></MenuLauncher>
</div>
</div>`,
});
window.app.component('MenuLauncher', window.externalComponents.MenuLauncher)
window.app.component('ThemeWrapper', window.externalComponents.ThemeWrapper)
window.app.mount("#app");
});
</script>
</body>
</html>
Preview of end result:
Desired result:
MenuLauncherVue
component should be able to render within ThemeWrapper
component.