前言
本来上篇最后说第二篇准备写 几个页面的小功能在微前端里的发布使用,但是目前没有找到最优方式,所以第二篇准备水微前端吧,虽然话题有点烂,写的人也挺多了,但是目前在搞这个,所以再...水一篇
吐槽
为什么上微前端还是都搞成一个镜像包,项目到了线上之后,每次更新都要影响别的应用,我觉得这是真的难以接受,后面我会说一下我目前的处理方式。
准备
- 目前微前端用的大都是qiankun,它是基于single-spa封装的,虽然刚开始应用的有一些问题,但是它放出来的有个常见问题梳理,大多的问题都能够解决。
- 确定主应用的技术框架,根据qiankun配置主应用,同时使用docker,CICD等
- 封装一or N个纯净版的子应用框架,如果子应用的技术团队内确定,那么封装一个就够了,但是既然上了微前端,那么至少vue和react的子应用还是都要用用的
- 其它的就是一些基本的开发常规操作了,根据自身项目的需求引用就好了
正式篇
- 配置main.js,其实最主要的就是引入micro和启用微应用功能
import { microApps } from '@/micro'
new Vue({
}).$mount('#app').$nextTick(() => {
microApps.start()
})
2.配置index.js,引入qiankun的功能,注册微应用,给子应用提供一些在主应用里可操作的能力,批量处理一下子应用的入口
const microAppConfig = micros.map(micro => {
setGlobalState({
//提供子应用的能力
})
})
registerMicroApps(microAppConfigs, (() => {
return {
通知子项目,for example 被移除
}
})
-
在这里说一下,我在刚开始写的时候,有个子应用跳转到主应用的时候,会产生css未加载的问题,然后在这里处理了一下
const childRoute = microAppConfigs.map(app => { if (Array.isArray(app.activeRule)) { return app.activeRule.map(rule => { return rule.replace('/#/', '/') }) } else { return [app.activeRule.replace('/#/', '/')] } }).flat()
- 配置下子应用的main.js
//渲染 与主应用 registerMicroApps 中的 activeRule 字段对应
const render = (props = {}) => {
const { container } = props
instance = new Vue({
render: h => h(App)
}).$mount(container ? container.querySelector('#app') : '#app')
}
export async function bootstrap(props) {
console.log('bootstrap', props)
}
// 判断qiankun环境
const __qiankun__ = window.__POWERED_BY_QIANKUN__
// 全局方法挂载
Vue.prototype.__qiankun__ = window.__POWERED_BY_QIANKUN__
if (__qiankun__) {
// 这里调用主项目传过来的关闭方法
}
export async function mount(props) {
// 导出生命周期 挂载前 挂载后; 注意实例化路由时,判断当运行在qiankun环境时,路由要添加前缀,前缀与主应用注册子应用函数genActiveRule()内的参数一致
onGlobalStateChange(async(state) => {
})
window.addEventListener('MicroAppDelView', microAppDelViewHandle)
}
export async function unmount() {
// 导出生命周期 挂载前 卸载后
window.removeEventListener('MicroAppDelView', microAppDelViewHandle)
}
if (!__qiankun__) {
render()
}
- 在permission里处理一下路由表
router.addRoutes() // 动态添加可访问路由表
设计&处理
项目是上了自动化,所以省了很多事,每个应用单独打的镜像,在跑CI的时候是增量部署,特别是主应用的,因为之前不知道谁用了全量部署,导致了子应用被冲掉(部署模式问题:删除yml的--delete改成增量模式,防止文件被覆盖删除)。
要考虑到子应用挂载到主应用的时候基座问题,不然会频繁报错。
主应用和子应用切换的时候,在去年的时候会产生切换跳转失效的问题,具体是第一次加载正常,项目tabs正常挂载,跳转主应用时子项目被销毁,子项目二次挂载的时候,tabs在主应用失效,第一种是router 有两个 app 实例导致,还有一种是路由不匹配导致。解决办法:销毁是否生效,如果生效,升级路由版本。
single-spa的query携带中文会导致项目stuck,需要设置urlRerouteOnly: true,但是如果设置了那么会产生另外一个问题,通过外链跳入项目会无法加载页面,这个我不太记得清最后是怎么处理的了,当时扒了下single-spa的源码,然后做了个编译,升级路由之后这个问题好像也没发生过了。