qiankun迁移micro-app填坑记录

473 阅读2分钟

由于目前手里的项目是之前从外包接过来的,是基于qiankun 2.0的微前端项目主应用和子应用都是vue2为技术栈搭建的,由于不支持vite,所以迁移到了micro-app,本来是想等qiankun3.0的,看目前进度有点慢。

微应用img,css使用相对路径被替换为基座应用地址

解决办法就是重写原型链上部分方法和属性替换为子应用地址

  //处理img
  Object.defineProperty(HTMLImageElement.prototype, 'src', {
    set(e) {
      const flag = ['http', 'blob:'].every((x) => !e.startsWith(x))
      if (window.__MICRO_APP_PROXY_WINDOW__ && e && flag) {
        const origin = window.__MICRO_APP_PROXY_WINDOW__.location.origin
        e = origin + e
      }

      this.setAttribute('src', e)
    }
  })

 //处理css
  const rawSetAttribute = HTMLLinkElement.prototype.setAttribute
  HTMLLinkElement.prototype.setAttribute = function (key, value) {
    if (key == 'href' && this.parentNode.tagName.toLowerCase() == 'micro-app-head') {
      const origin = window.__MICRO_APP_PROXY_WINDOW__.location.origin
      value = value?.replace(window.location.origin, origin)
    }

    rawSetAttribute.call(this, key, value)
  }
微应用使用window.open跳转其他微应用路由

解决办法就是重写window.open地址指向基座应用,因为基座应用路由栈和微应用路由栈是隔离的

//由于microapp沙箱中的window对象是代理,所以子应用的window路由是与主应用隔离的,所以重写open方法
//举个例子:
// const microAppList = [
//   {
//     name: 'test',
//     entry: 'https://xxxx/',
//     activeRule: `/index/test`,
//   }
// ]

//由于microapp沙箱子应用的window路由是与主应用隔离的,所以重写open方法
const originalWindowOpen = window.open
const ruleSign = '/index/'
const validateStartArr = ['http', ruleSign]
window.open = function (url, target, features) {
  const app = microAppList.find((el) => url.startsWith(el.entry))
  if (app) {
    const wlOrigin = window.location.origin
    const origin = !url.includes(ruleSign) ? wlOrigin + app.activeRule : wlOrigin
    url = url.replace(app.entry, origin)
  } else if (
    validateStartArr.every((v) => !url.startsWith(v)) &&
    localRoutes.some(({ path }) => !url.startsWith(path) && path != '/')
  ) {
    url = window.location.origin + preApp?.activeRule + url
  }

  return originalWindowOpen(url, target, features)
}
基座应用和微应用路由跳转和地址同步的问题

因为基座路由栈和微应用路由栈是隔离的,改动每一个微应用代价太大,所以所有跳转统一在基座路由处理

 //基座跳转微应用
  microApp.router.replace({
    name: 'test',
    path: 'https://xxx/x?xx=123',
    replace: true
  })
 
 //微应用跳转微应用建议在路由拦截器,使用history.replaceState将错误路由替换掉
const currentState = history.state || {}
history.replaceState(currentState, document.title, '正确路由')
  
//微应用内部跳转导致基座应用地址未变更,强制同步
microApp.router.afterEach(() => {
  const location = window.__MICRO_APP_PROXY_WINDOW__?.location
  const pathname = location?.pathname
  if (!location || !preApp || window.location.pathname.includes(pathname || '')) return
  const url = preApp?.activeRule + location.pathname + location.search
  history.replaceState(history.state || {}, document.title, url)
})

总结:micro-app的坑不比qiankun少,micro-app路由处理尤其麻烦,qiankun路由这一块可以少很多心智负担,至于性能都差不多,内存占用qiankun是最好的,micro-app平均多100mb占用,至于对微应用的改造适配,感觉工作量都差不多,不是网上说的那么简单,总之适合才是最好的