微前端技术栈 Vue3 + vite + ts
基座配置
基座采用是的 Vue3 + vite + ts,只负责导航的渲染和登录态的下发,为子应用提供一个挂载的容器div,
npm i qiankun
qiankun这个库只需要在基座引入,在main.ts 中注册子应用,为了方便管理,我们将子应用的配置都放在:/src/qiankun.js下
import {
registerMicroApps, addGlobalUncaughtErrorHandler, start } from 'qiankun';
import router from './router'
// 注册子应用
registerMicroApps([
{
// 子应用名称,name值必须与子应用vite.config.ts文件中plugins属性qiankun的第一个参数值一致
name: 'subApp',
// 默认会加载这个路径下的html,解析里面的js
entry: '//localhost:5050/',
// 加载的容器(微应用会显示到这个容器里面,一定要保证主应用中有这个容器)
container: '#subAppContainerVue3', // 和app.vue配置的节点一致
// 匹配的路由
activeRule: '/gosubsystem', // 访问:http://localhost:5174/juminronghe
props: {
mag: '我是主应用main', // 主应用向微应用传递参数
},
},
{
// 子应用名称,name值必须与子应用vite.config.ts文件中plugins属性qiankun的第一个参数值一致
name: 'lmsApp',
// 默认会加载这个路径下的html,解析里面的js
entry: '//localhost:5000/',
// 加载的容器(微应用会显示到这个容器里面,一定要保证主应用中有这个容器)
container: '#subAppContainerVue3', // 和app.vue配置的节点一致
// 匹配的路由
activeRule: '/lmsApp',
props: {
mag: '我是主应用main', // 主应用向微应用传递参数
router // 主路由下发到子路由,子应用路由跳转使用主应用路由实例跳转(需要跳转的路由要在主应用里注册)
},
}
],
{
beforeLoad: app => {
console.log('before load app.name====>>>>>', app.name)
},
beforeMount: [
app => {
console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name);
},
],
afterMount: [
app => {
console.log('[LifeCycle] after mount %c%s', 'color: green;', app.name);
}
],
afterUnmount: [
app => {
console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name);
},
],
});
// 启动 qiankun
// start({
// prefetch:'all', // 预加载
// sandbox: {
// experimentalStyleIsolation: true, // 开启沙箱模式,实验性方案
// },
// });
// 添加全局异常捕获
addGlobalUncaughtErrorHandler((event) => {
// console.error(event);
const {
message: msg } = event;
// 加载失败时提示
if (msg && msg.includes("died in status LOADING_SOURCE_CODE")) {
// message.error("微应用加载失败,请检查应用是否可运行");
console.log("微应用加载失败,请检查应用是否可运行-乾坤插件是否正常")
}
});
然后在src/main.ts中引入
import './qiankun.js';
如何在主应用的某个路由页面加载微应用
必须保证微应用加载时主应用这个路由页面也加载了
主应用注册这个路由时给 path 加一个 *,注意:如果这个路由有其他子路由,需要另外注册一个路由,仍然使用这个组件即可
{
path: '/portal/*',
name: 'portal',
component: () => import('../views/Portal.vue'),
},
Portal.vue
<template>
<div id="subAppContainerVue3"></div>
</template>
<script lang="ts" setup name="merchantsRuquest">
// import start from "@/qiankun/index.js";
import {
start } from 'qiankun'
// import { registerApps } from '@/qiankun/index.js'
onMounted(()=>{
if (!window.qiankunStarted) {
window.qiankunStarted = true
// registerApps()
start({
sandbox: {
experimentalStyleIsolation: true // 样式隔离
}
})
}
})
// export default {
// mounted() {
// }
// }
</script>
主应用路由配置
{
path: '/lmsApp/*', // 注意和registerMicroApps 注册子应用的activeRule匹配
name: 'lmsApp',
meta: {
title: "子应用菜单管理",
icon: "car-outlined",
isFull: false,
isKeepAlive: true,
isHide: false
},
children: [
{
name: 'xxxxx',
path: '/lmsApp/xxxx/xxxxx',
component: () => import('@/views/portal.vue'),
meta: {
title: '子应用菜单下的二级菜单',
icon: '',
isKeepAlive: false
}
},
]
},
这样,基座就算配置完成了。项目启动后,子应用将会挂载到主应用中
子应用配置
安装vite-plugin-qiankun
npm i vite-plugin-qiankun --save-dev
修改vite.config.ts
import qiankun from 'vite-plugin-qiankun'
引入乾坤插件
plugins: [ vue(), qiankun('app-vue3', { useDevMode: true }) ],
使用
在子应用main.ts 里引用qiankun
import {
renderWithQiankun,
qiankunWindow,
type QiankunProps
} from 'vite-plugin-qiankun/dist/helper'
let app: any
const render = (container?: any, routers?: any) => {
app = createApp(App)
Object.keys(Icons).forEach((key) => {
app.component(key, Icons[key as keyof typeof Icons])
})
app.use(pinia)
app.use(print)
app.use(Antd)
app.use(directives)
app.config.globalProperties.$routers = routers
app.use(router).mount(container ? container.querySelector('#app') : '#app')
}
const initQianKun = () => {
renderWithQiankun({
mount(props) {
// localStorage.lalal = 111111
console.log(props.router, '获取主应用传递数据')
sessionStorage.latoutStatus = false
const {
container, router } = props
render(container, router)
},
bootstrap() {
},
unmount() {
app.unmount()
},
update: function (props: QiankunProps): void | Promise<void> {
throw new Error('Function not implemented.')
}
})
}
// console.log(qiankunWindow.__POWERED_BY_QIANKUN__, '90')
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
由于路由模式为history,需要匹配子应用的入口规则,修改src/router/index
import {
qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const router = createRouter({
history: createWebHistory(
qiankunWindow.__POWERED_BY_QIANKUN__
? '/lmsApp/'
: '/'
),
routes
})
至此,本地运行的所有配置全部修改完