前言
- 主应用和微应用技术栈都是vue3+vite
- 主应用需要安装qiankun插件
- 微应用需要安装vite-plugin-qiankun插件
主应用相关操作
安装 npm i qiankun -S 插件
新建文件夹(qiankun)
在src目录下面新建一个qiankun的文件夹,存放qiankun相关的文件,方便后续的管理和查找。
主文件
在qiankun文件夹里面新建main.js文件。文件内容如下:
import { registerMicroApps } from 'qiankun'
// 导入所有的微应用
import subAppConfig from '@/qiankun/subAppConfig' // 微应用的配置文件的路径
const { subApps } = subAppConfig
export function registerApps() {
try {
registerMicroApps(subApps, {
beforeLoad: [
(app) => {
console.log('before load', app)
},
],
beforeMount: [
(app) => {
console.log('before mount', app)
},
],
afterUnmount: [
(app) => {
console.log('before unmount', app)
},
],
})
} catch (err) {
console.log(err)
}
}
容器配置(用于渲染微应用)
新建一个src/components/SubContainer.vue组件,用于存放微应用。
<template>
<!-- 容器的id。微应用配置的时候需要 -->
<div id="sub-container"></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import { start } from 'qiankun'
// 引入qiankun
import { registerApps } from '@/qiankun/main.js' // qiankun主文件的路径
onMounted(() => {
if (!window.qiankunStarted) {
window.qiankunStarted = true
registerApps()
// 开启qiankun
start({
// sandbox: {
// // sandbox: { strictStyleIsolation: true } // 严格隔离
// // experimentalStyleIsolation: true // 样式隔离
// }
})
}
})
</script>
微应用配置文件
在qiankun文件夹里面新建subAppConfig.js。存放子应用配置,可以配置多个子应用。
const subApps = [
{
name: 'SubAppName', // 子应用名称,保持唯一性。在微应用中会使用到。
container: '#sub-container', // 微应用挂载的容器的id。 SubContainer组件中声明的id名
activeRule: '/app/app-vue3', // 主应用响应的路由信息。 即当访问到这个路由下面的路由,都是微应用的路由。router.js文件配置的path
entry: '//localhost:7788', // 子应用网址。 本地环境下指定端口。当主应用匹配到activeRule时,会被转发到当前设置的链接下面。
props: {}, // 主应用与子应用通信传值
},
]
export default {
subApps,
}
参考图片 更好理解
配置router文件
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: () => import('@/views/HomeView.vue'),
},
{
path: '/table',
name: 'table',
component: () => import('@/views/TableView.vue'),
},
{
path: '/table2',
name: 'table2',
component: () => import('@/views/TableView.vue'),
},
{
path: '/table3',
name: 'table3',
component: () => import('@/views/TableView.vue'),
},
{
// history模式需要通配所有路由,详见vue-router文档
path: '/app/app-vue3/:pathMatch(.*)*',
name: 'app-vue3',
meta: {},
// 微应用组件的容器
component: () => import('@/components/SubContainer.vue'),
},
],
})
export default router
启动项目,正常打开页面。访问结束。
微应用
安装 npm i vite-plugin-qiankun -S 插件
vite.config.js里面配置qiankun
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// import vueDevTools from 'vite-plugin-vue-devtools'
import qiankun from 'vite-plugin-qiankun'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
// vueDevTools(),
qiankun(
'SubAppName', // 主应用里面配置的微应用的name
{
useDevMode: true,
},
),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
server: {
port: 7788,
open: false,
},
})
history模式,修改一下router文件
import { createRouter, createWebHistory } from 'vue-router'
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const router = createRouter({
history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/app/app-vue3/' : '/'),
routes: [
{
path: '/',
name: 'home',
component: () => import('@/views/HomeView.vue'),
},
{
path: '/table',
name: 'table',
component: () => import('@/views/TableView.vue'),
},
{
path: '/table2',
name: 'table2',
component: () => import('@/views/TableView.vue'),
},
{
path: '/table3',
name: 'table3',
component: () => import('@/views/TableView.vue'),
},
],
})
export default router
main.ts中引入配置qiankun
import './assets/reset.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/reset.css'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
import router from './router'
import Layout from './components/layout/index.vue'
let app = null
const render = (container) => {
app = createApp(Layout)
app.use(createPinia())
app.use(router)
app.use(Antd)
app.mount(container ? container.querySelector('#app') : '#app')
}
const initQianKun = () => {
renderWithQiankun({
mount(props) {
const { container } = props
render(container)
},
bootstrap() {},
unmount() {
app.unmount()
},
})
}
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
启动项目,运行没问题。
两者访问
微应用 http://localhost:7788
主应用 http://localhost:6677
修改主应用的菜单
当点击sub app菜单时,即访问了http://localhost:6677/app/app-vue3/table2
根据qiankun配置的activeRule,相当于访问了http://localhost:7788/table2 。
只不过访问的这个地址会以组件的形式在主应用渲染,因为微应用配置文件中配置了挂载的组件id
通过上面的图可以看到,微应用的页面被渲染到了SubContainer组件里面
微应用菜单栏的处理
当我们什么也不做的时候,会把整个微应用的页面渲染到主应用的内容区域
如图,其实我们只是想要微应用的内容区域。需要去除图中红色的部分。
解决方案: 修改微应用中的布局文件
通过qiankunWindow.POWERED_BY_QIANKUN 来判断当前是否在主应用下,动态渲染布局文件
tips
当主应用在访问子应用的路由时,子应用关闭,会出现如上错误。子应用访问不到
关于路由选择
| 主应用路由 | 微应用路由 | 特殊设置 |
|---|---|---|
| history | history | 微应用需要设置 base。eg: history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/app/app-vue3/' : '/'), |
| history | hash | 无设置 |
| hash | history | activeRule 前面加个#(但是不推荐这种方案) |
| hash | hash | activeRule 前面加个#。 另外需要改写微应用的路由结构,在外面嵌套一层。嵌套的外层就是主应用设置的路径 |