Configuring a Vue 3 Host with qiankun for Multi-Framework Micro-Applications
Host Shell: Vue 3.2+ / Vite 4+ Sub-Applications: Vue 3.2+, Angular 14+, React 18+
Host Application Configuration
Initialize standard Vue Router and navigation structure first. Within your primary layout component, define a dedicated rendering zone for child applications.
<template>
<div class="shell-layout">
<nav>
<router-link to="/">Home</router-link>
<router-link to="/sub/vue">Vue Module</router-link>
<router-link to="/sub/ng">Angular Module</router-link>
<router-link to="/sub/react">React Module</router-link>
</nav>
<hr />
<main id="render-zone"></main>
</div>
</template>
Proceed with installing the micro-frontend runtime:
npm install qiankun --save
Create an application registration file microAppsRegistry.ts:
import { registerMicroApps, start, LifeCycleFn } from 'qiankun';
type AppLifecycle = {
beforeLoad?: LifeCycleFn;
beforeMount?: LifeCycleFn;
afterUnmount?: LifeCycleFn;
};
const appsToRegister = [
{
name: 'vue-sub-module',
entry: '//localhost:8080',
container: '#render-zone',
activeRule: '/sub/vue',
props: { theme: 'dark' }
},
{
name: 'angular-sub-module',
entry: '//localhost:4200',
container: '#render-zone',
activeRule: '/sub/ng',
props: { lang: 'en' }
},
{
name: 'react-sub-module',
entry: '//localhost:3000',
container: '#render-zone',
activeRule: '/sub/react',
props: { version: 'latest' }
}
];
const lifecycleHooks: AppLifecycle = {
beforeLoad: async () => console.log('Module loading initiated'),
beforeMount: async () => console.log('Mount phase started'),
afterUnmount: async () => console.log('Cleanup complete')
};
registerMicroApps(appsToRegister, lifecycleHooks);
start({
sandbox: {
strictStyleIsolation: true,
experimentalStyleIsolation: true
},
prefetch: true
});
Import this registry into your Vue entry point src/main.ts:
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import './microAppsRegistry';
createApp(App).use(router).mount('#app');
Vue 3 Sub-Application Setup
Standard routing configuration remains unchanged. To enable qiankun compatibility within a Vite environment, integrate the dedicated adapter plugin:
npm install vite-plugin-qiankun --save-dev
Adjust the build configuration in vite.micro.config.ts:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import qiankunPlugin from 'vite-plugin-qiankun';
export default defineConfig({
base: '/sub/vue/',
plugins: [
vue(),
qiankunPlugin('vue-sub-module', { useDevMode: true })
],
server: {
host: '0.0.0.0',
port: 8080,
cors: true,
origin: 'http://localhost:8080'
}
});
Refactor the application bootstrap logic in src/index.ts to handle external hosting environments:
import { createApp } from 'vue';
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
import RootComponent from './App.vue';
import applicationRouter from './router';
let instanceCache: any = null;
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
// Standalone execution mode
const app = createApp(RootComponent);
app.use(applicationRouter);
app.mount('#app');
} else {
renderWithQiankun({
mount(props) {
instanceCache = createApp(RootComponent);
instanceCache.use(applicationRouter);
instanceCache.mount(props.container?.querySelector('#app') || document.getElementById('app'));
},
unmount() {
instanceCache?.unmount();
instanceCache = null;
},
update(props) {
console.log('Props updated:', props);
}
});
}
Angular Sub-Application Configuration
For Angular integration, the ecosystem relies on single-spa-angular. Initialize a fresh project with routing enabled:
ng new angular-micro-app --routing --prefix micro-ang
cd angular-micro-app
ng add single-spa-angular --project angular-micro-app
Modify main.single-spa.ts to inject the correct base href and lifecycle definitions:
import { APP_BASE_HREF } from '@angular/common';
import { singleSpaAngular, SingleSpaAngularOptions } from 'single-spa-angular';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
const extraProviders = [];
const angularLifecycles: SingleSpaAngularOptions<any> = {
bootstrapFunction: (singleSpaProps) => {
return platformBrowserDynamic(extraProviders)
.bootstrapModule(AppModule)
.catch(err => console.error(err));
},
template: '<micro-ang-root id="child-ng-instance"/>',
Router: undefined,
NgZone: undefined
};
export default singleSpaAngular(angularLifecycles);
Configure the routing module to dynamically set the base path based on the execution context. Ensure this matches the host's activeRule:
import { NgModule } from '@angular/core';
import { RouterModule, Routes, APP_BASE_HREF } from '@angular/router';
const routes: Routes = []; // Define your actual routes here
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [
{
provide: APP_BASE_HREF,
useValue: window['__POWERED_BY_QIANKUN__'] ? '/sub/ng' : '/'
}
]
})
export class AppRoutingModule {}
Update the root component selector and template wrapper to prevent DOM conflicts when multiple instances exist:
import { Component } from '@angular/core';
@Component({
selector: '#child-ng-instance micro-ang-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {}
To allow independent local development while maintaining qiankun compatibility, modify the bootstrapping logic:
// Inside main.single-spa.ts or bootstrap file
import 'zone.js/dist/zone';
if (!(window as any).__POWERED_BY_QIANKUN__) {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}
If polyfills interfere with standalone runs, remove import 'zone.js' from polyfills.ts. Ensure the host application manages zone.js dependencies to avoid duplicate runtime injections.
React Sub-Application Considerations
React modules require the official @ice/stark or single-spa-react adapter. Configure entry points to export standard mounting/unmounting functions. Apply CSS scoping strategies and isolate global state to prevent framwork interference. Follow the same lifecycle pattern established in the Vue implementation.