2024-07-17-微前端框架之乾坤qiankun-vue3viteqiankun手把手搭建版
微前端框架之乾坤【qiankun】 vue3+vite+qiankun(手把手搭建版)
前言
简介:qiankun是一种微前端框架,可以将多个前端应用集成为一个整体。每个子应用可以使用不同的框架和技术栈,它们之间可以相互独立开发和部署,qiankun提供了一套完整的生命周期函数和通信机制,可以让不同的子应用之间进行跨框架和跨域的通信和交互
具体查看官网:
业务场景
描述图:
描述:
base 基础框架为主应用,包括左侧菜单部分,顶部头部部份,也是qiankun中主应用。
子应用:wms,wcs…等应用在右侧展示区展示
关联: 通过点击左侧菜单加载对应的子应用页面
乾坤的使用(主应用和子应用)
主应用配置
1,安装依赖
$ yarn add qiankun # 或者 npm i qiankun -S
$ yarn add vite-plugin-qiankun 或者 npm i vite-plugin-qiankun -S
$ yarn add vite-plugin-qiankun/dist/helper 或者npm i vite-plugin-qiankun/dist/helper -S
2,main.ts配置
关键代码:
import apps from './qiankun.js'
import { registerMicroApps, addGlobalUncaughtErrorHandler } from 'qiankun'
// 注册微应用
registerMicroApps(apps, {
beforeLoad: () => console.log('before load'),
beforeMount: [() => console.log('before mount')],
afterMount: () => console.log('*********'),
beforeUnmount: () => console.log('****beforeUnmount *****'),
afterUnmount: () => console.log('-------afterUnmount *********---')
})
// 全局的未捕获异常处理器
addGlobalUncaughtErrorHandler(event => {
console.log(event)
})
registerMicroApps:注册子应用信息的api
addGlobalUncaughtErrorHandler :捕获qiankun 运行时的异常错误信息
详见文档:
qiankun.js: 自定义子应用注册时的一些信息
3,qianjun.js 文件
关键代码:
import actions from './actions'
const microApps = [
{
name: 'wmsApp',
entry: '/baseWms/', //本地http://localhost:9002:baseWms
activeRule: '/wms'
}
// {
// name: 'app-vue1',
// entry: '//localhost:8003/app-vue1/',
// activeRule: '/app-vue1'
// }
]
const apps = microApps.map(app => {
return {
...app,
container: '#app-micro',
props: {
routerBase: app.activeRule, // 下发基础路由
temmpData: { name: '小强', age: 25 },
parentActions: actions
},
loader(loading) {
console.log('loading', loading)
}
}
})
export default apps
1,name:子应用的命名,
2,entry 子应用进入的地址,通过 配合 activeRule触发进入
注意点:这个 名字可以随便填写,生成环境nginx 配置必须一致
3,activeRule 触发子应用的标识,在这里,得注意 不能和entry 相同,否则会出现进入子应用刷新后覆盖父应用bug
4, container 子应用触发后,内容挂载区域,我这里定义id 等于app-micro,此文件自定义为qiankun.vue(后面会在路由配置一块详细描述)
5,props :父应用向子应用传参(可以传自定义参数,也可以传父应用中qiankun相关函数)这里我将主应用的相关qiankun 全局监听函数写在了action.js类
4,action.js 文件
关键代码:
import { initGlobalState } from 'qiankun'
// import { useRouter, useRoute } from 'vue-router'
import router from './router/index'
const state = {
// num: 1,
// name: 'codeFirst'
}
// 初始化 state
const actions = initGlobalState(state)
actions.onGlobalStateChange((state, prev) => {
console.log('主应用检测到state变更父级', state)
console.log('主应用检测到state变更父级', router)
// let {goParent:true} = state
// let url = state.url.replace('/wms/', '')
router.push(state.url)
})
// 你还可以定义一个获取state的方法下发到子应用
// actions.getGlobalState = function () {
// return state
// }
export default actions
initGlobalState:定义全局状态,并返回通信方法,建议在主应用使用,微应用通过 props 获取通信方法。
onGlobalStateChange:用来监听全局状态,主要监听子应用传什么给父应用,父应用需要做什么操作,此代码是子应用传了url 通知父应用进行跳转
具体看官网
5,router.js 文件
关键代码1:
// qiankunWindow.__POWERED_BY_QIANKUN__ ? '/wms/' :
const base = '/'
console.log(baseRoutes, 'baseRoutes*********************')
const router = createRouter({
history: createWebHistory(base), //createWebHashHistory() hash模式
routes: baseRoutes
})
注意点:
1,使用 qiankun 路由方式必须改为 createWebHistory
2,qiankunWindow.__POWERED_BY_QIANKUN__是可以用来判断qiankun是否启用
3,实时注册路由的时候,把push 改为 replace 之前测试时出现浏览器前进后退地址返回问题
6,base.js 文件
关键代码:
//更改后的
{
path: '/wms/:pathMatch(.*)*',
component: () => import('@/views/qiankun.vue'),
meta: { title: 'xxx', icon: 'icon-home' }
},
结合第3部分 qiankun.js,有个activeRule触发条件,这里我使用/wms 作为触发子应用的 标识,然后通过配置路由跳转到qiankun.vue 文件
之后如果加了子应用 wcs, 也可以配置对应的activeRule跳转到qiankun.vue 文件,其它子应用配置一样
7,qiankun.vue 文件
关键代码:
<script lang="ts">
import { defineComponent, reactive } from 'vue'
import { start } from 'qiankun'
import { useRouter, useRoute } from 'vue-router'
export default defineComponent({
setup() {
return reactive({
path: useRoute().path,
microApp: '' as any
})
},
created() {},
deactivated() {
window.qiankunStarted = false
},
async mounted() {
if (!window.qiankunStarted) {
window.qiankunStarted = true
start()
} else {
const router = useRouter()
const route = useRoute()
}
},
activated() {},
updated() {},
methods: {
// restartQianKun() {
// window.qiankunStarted = true
// console.log('我刚进来了乾坤1111')
// start()
// },
// startQianKun() {
// if (!window.qiankunStarted) {
// console.log('我刚进来了乾坤')
// this.restartQianKun()
// }
// }
}
})
</script>
<template>
<div id="app-micro"></div>
</template>
start:是 qiankun自带的api ,主要是开启qiankun
在进入页面的时候,首先判断qiankun是否开启,没有开启则开启
注意点 window.qiankunStarted = false 写在页面离开的生命周期自己写的一个处理,看过很多资料,qiankun没有手动关闭,自己内部会处理,此处可以不加
div的是元素挂载区域,与第3部分中 container 对应
8,vite.config.ts文件
注意点:
这段代码 必须加上,不然本次本地跑不起来,发布到线上主应用也打不开
子应用配置
1,安装依赖
$ yarn add qiankun # 或者 npm i qiankun -S
$ yarn add vite-plugin-qiankun 或者 npm i vite-plugin-qiankun -S
$ yarn add vite-plugin-qiankun/dist/helper 或者npm i vite-plugin-qiankun/dist/helper -S
2,main.ts配置
关键代码:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { renderWithQiankun, qiankunWindow, QiankunProps } from 'vite-plugin-qiankun/dist/helper'
let app
function render(props = {}) {
console.log(props, 'props-----------')
const { container, routerBase = '/wms' } = props
// const router = createRouter({
// routes,
// history: createWebHistory()
// })
app = createApp(App)
// app.use(store).use(router).mount('#child')
app
.use(store)
.use(router)
.mount(container ? container : '#child')
app.config.globalProperties.parentActions = props.parentActions
//app.use(store).mount(container ? container : '#child')
}
function qianKunControll() {
renderWithQiankun({
bootstrap() {
console.log('888888888----')
},
mount(props) {
// actions.actions.setGlobalState({
// parentActions: props
// })
console.log(props, 'props----123')
render(props)
},
unmount() {
app.unmount()
app = null
},
update: function (props: QiankunProps): void | Promise<void> {
console.log('woshi chilid upadte----')
}
})
}
if (qiankunWindow.__POWERED_BY_QIANKUN__) {
qianKunControll()
}
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render()
console.log('独立运行')
}
renderWithQiankun: 加载qiankun的生命周期,必须添加,否则子应用与父应用直接无法正常运行通信,其中
mount生命周期用来加载父应用传过来的参数并挂载渲染
unmount:这个生命周期用来处理每次挂载在父应用容器中的页面元素,每次子应用离开进行卸载
bootstrap: 初始化子应用 很少用
update:子应用更新改变 很少用
render 函数用来渲染子应用
props 就是父应用传过来的 props 具体看主应用的 qiankun.js文件
如果主应用 传来props 证明qiankun状态中,则子应用挂载在父应用,否则子应用独立运行挂载在自己的index.html div容器中
app.config.globalProperties.parentActions = props.parentActions 主要将父应用的qiankun全局监听函数保存起来,作用是在任何地方使用父应用中监听函数,从而通知父应用。可以理解为qiankun 的父子通信。
2,router下面index.js
细节问题:base 路径必须和 父应用qiankun.js 中activeRule 一致,否则跑起来各种问题,这里我理解为 通过根据访问的域名地址,去找对应的资源地址,比如 127.0.0.1/wms/index 会找wms下面的资源
引入 的qiankunwindow 是用来判断是否为qiankun状态从而进行逻辑判断 ,此次没有用到
3,vite.config.js
注意点:
本地开发环境中 base 改为 ./ 生产必须改成 和 父应用 entry一致 这里是 baseWms
注意点:
这里必须加上,qiankun会解析,并且第一个参数的名称必须和 父应用 qiankun.js中name 一致
部署部分(待补充)
1,nginx
关键代码:
location / {
root E:\\微前端\\base-project\\dist;
index index.html /index.htm;
try_files $uri $uri/ /index.html;
}
location /wms {
# root E:\\微前端\\base-project\\dist\\baseWms;
# index index.html /index.htm;
# try_files $uri $uri/ /index.html;
proxy_pass http://127.0.0.1:8091;
}
server {
listen 8091;
server_name 127.0.0.1;
location / {
root E:\\微前端\\base-project\\dist\\baseWms;
index index.html /index.htm;
try_files $uri $uri/ /index.html;
}
}
1,目前出现过的问题,主应用和子应用跳转正常,但是跳转结束后,刷新 404 ,解决办法,使用: proxy_pass http://127.0.0.1:8091;进行跳转
2,目前还未解决遇到的 问题,正常直接访问子应用 属于独立访问,那么不会启动qiankun,此时其实父应用和子应用ip一致,无法加载父应用base基础数据,解决思路,nginx中父子应用都独立配置相同ip不同端口,比如 127.0.0.1:9001 和127.0.0.1:9002
3,其它问题,比如样式隔离,数据共享资源问题,等等可能存在的问题(暂时未出现)
qiankun使用总结:
1,基于 single-spa 封装了更加开箱即用的api
2,与技术栈无关可以vue react angular 等框架一起使用
3,样式隔离 (目前一个主,和一个子没问题)
4,js沙箱(目前一个主,和一个子没问题)
5,提供完整的父子通信api和数据共享模式,也可以通过路由传参,缓存等方式进行数据共享
6, 子应用静态资源预加载 只需在start中配置 prefetch (具体看文档)
使用问题:
1,如果有多个子应用,乾坤会一次加载,所以只要拥有一个子应用配置错误,乾坤启动失败
68747470733a2f2f62:6c6f672e6373646e2e6e65742f6d305f35313430303934382f:61727469636c652f64657461696c732f313430343338393435