自己近期仿照qiankun官方demo做了个小型的微前端demo尝鲜,主应用用的vue3.0框架,分别创建了react17版本,react16版本、vue2.0版本等子应用。后续帖子会逐步做API公共方法抽离。目前只是个尝鲜demo。
主应用html结构
<%= htmlWebpackPlugin.options.title %>
QianKun-Main
主应用挂载区
Loading...
主应用main配置:
import { createApp } from "vue";
import "../public/index.less";
// 导入qiankun内置函数
import {
registerMicroApps,
runAfterFirstMounted,
setDefaultMountApp,
start,
initGlobalState,
} from "qiankun";
import App from "./App.vue";
/**
* @description:第一步:render渲染函数
*
*
*/
let app = null;
/**
* 渲染函数
* appContent 子应用html
* loading 如果主应用设置loading效果,可不要
*/
function vueRender({ loading }) {
return createApp(App, { loading: loading }).mount("#subapp-container");
}
function render({ loading }) {
if (!app) {
app = vueRender({ loading });
}
}
/**
* 路由监听
* @param {*} routerPrefix 前缀
*/
// function genActiveRule(routerPrefix) {
// return (location) => location.pathname.startsWith(routerPrefix);
// }
// 调用渲染主应用
render({ loading: true });
const loader = (loading) => render({ loading });
/**
* @description:第二步:主应用注册引入子应用
*
*
*/
registerMicroApps(
[
{
name: "react17",
entry: "//localhost:3000",
container: "#subapp-viewport",
activeRule: "/react17",
loader,
props: {
name: "kuitos",
},
},
{
name: "react16",
entry: "//localhost:7100",
container: "#subapp-viewport",
activeRule: "/react16",
loader,
props: {
name: "react16",
},
},
{
name: "vue",
entry: "//localhost:7101",
container: "#subapp-viewport",
activeRule: "/vue",
loader,
props: {
name: "vue",
},
},
{
name: "vue-sub",
entry: "//localhost:7102",
container: "#subapp-viewport",
activeRule: "/vueSub",
loader,
props: {
name: "vue-sub",
},
},
],
{
beforeLoad: [(app) => console.log("before load", app.name)],
beforeMount: [(app) => console.log("before mount", app.name)],
afterUnmount: [(app) => console.log("before mount", app.name)],
}
);
const { onGlobalStateChange, setGlobalState } = initGlobalState({
user: "qiankun",
});
onGlobalStateChange((value, prev) =>
console.log("[onGlobalStateChange - master]:", value, prev)
);
setGlobalState({
ignore: "master",
user: {
name: "master",
},
});
/**
* Step3 设置默认进入的子应用
*/
setDefaultMountApp("/vueSub");
// 第一个子应用加载完毕回调
runAfterFirstMounted(() => {
console.log("[MainApp] first app mounted");
});
// 启动微服务
start();
// createApp(App).mount('#app')
子应用(vue2.0为例)配置
import './public-path';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';
Vue.config.productionTip = false;
Vue.use(ElementUI);
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/',
mode: 'history',
routes,
});
instance = new Vue({
router,
store,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
function storeTest(props) {
props.onGlobalStateChange &&
props.onGlobalStateChange(
(value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
true,
);
props.setGlobalState &&
props.setGlobalState({
ignore: props.name,
user: {
name: props.name,
},
});
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
storeTest(props);
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}