摸鱼之微前端及其配置

188 阅读3分钟

前言

本来上篇最后说第二篇准备写 几个页面的小功能在微前端里的发布使用,但是目前没有找到最优方式,所以第二篇准备水微前端吧,虽然话题有点烂,写的人也挺多了,但是目前在搞这个,所以再...水一篇

吐槽

为什么上微前端还是都搞成一个镜像包,项目到了线上之后,每次更新都要影响别的应用,我觉得这是真的难以接受,后面我会说一下我目前的处理方式。

准备

  • 目前微前端用的大都是qiankun,它是基于single-spa封装的,虽然刚开始应用的有一些问题,但是它放出来的有个常见问题梳理,大多的问题都能够解决。
  • 确定主应用的技术框架,根据qiankun配置主应用,同时使用docker,CICD等
  • 封装一or N个纯净版的子应用框架,如果子应用的技术团队内确定,那么封装一个就够了,但是既然上了微前端,那么至少vue和react的子应用还是都要用用的
  • 其它的就是一些基本的开发常规操作了,根据自身项目的需求引用就好了

正式篇

  1. 配置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()
    
  1. 配置下子应用的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的源码,然后做了个编译,升级路由之后这个问题好像也没发生过了。