# 子应用如何定义和使用

# Single-spa

几年前面世的 single-spa 解决了第一个问题,我们来看一下它的用法,截图自Single-spa 官网single-spa

我们可以看到,关键 api 是 registerApplication,这里需要传入 app,它一般是个函数,返回一个 promise,resolve 值需要包含 mount, unmount 和 bootstrap 等子应用生命周期方法,这个设计是比较有想象空间的,只要符合这个规则,我们可以自己去实现这个函数,加入自己的规则,Qiankun 正是这样做的。 另一个参数 activeWhen 就是根据路由加载子应用的规则,single-spa 会监听路由变化并劫持更改原生方法,应用路由判断逻辑。部分代码如下:

window.addEventListener("hashchange", urlReroute);
window.addEventListener("popstate", urlReroute);
window.history.pushState = patchedUpdateState(
  window.history.pushState,
  "pushState"
);

1
2
3
4
5
6
7

子应用加载之后,single-spa 会维护子应用的实例,再次激活时会直接使用。

# 如何动态加载和隔离

# Qiankun

首先看一下它的用法:

关键 api registerMicroApps 与 single-spa 类似,都是注册子应用,区别在于支持传入 html 地址或者前端资源地址的数组作为应用入口,根据约定,子应用需要暴露声明周期方法,Qiankun 会去加载资源然后根据约定拿到方法,这里官方的推荐是通过 webpack 的 umd 输出格式来做。在执行 js 资源时通过 eval,会将 window 绑定到一个 Proxy 对象上,以防污染全局变量,并方便对脚本的 window 相关操作做劫持处理,达到子应用之间的脚本隔离。 下面是截取的一些相关代码,逻辑还算比较容易看懂。

其中子应用代码真正的执行过程在拆分出来的 import-html-entry 模块中:

而样式隔离则是通过在 unmount 时卸载样式表自然地做到。 就这样,Qiankun 解决了加载和隔离,成为了一个完整的微前端方案。

# 有格微前端做了什么

# 微应用类型划分和手动加载处理

根据业务模块来划分出路由子应用和手动子应用。 定义和配置子应用的相关参数。 image.png 结合vue实现手动加载微应用的通用组件 image.png

# 微应用之间通信处理

  • 初期开发@h3yun/global-provider 来解决通信问题。在全局提供一个实例来做数据存储,通过observe dispatch的类redux方式来做数据传递,通过eventBus来做事件交互。
  • 但是由于通过 @h3yun/global-provider 来进行开发,过于灵活和分散,后期维护比较困难。因此梳理了业务模型,开发了@h3yun/opensdk,即集成框架来解决开发一致和维护问题。

# 提供本地开发接入能力

  • 基于Qiankun加载逻辑,通过动态修改子应用配置,来使本地应用接入到线上进行开发。

image.png 且为了测试和线上环境也能调试,同时不暴露调试方式,开发了浏览器插件。 同时浏览器插件支持 @h3yun/global-provider @h3yun/opensdk的数据,文档及性能展示功能。

image.png

# 应用聚合发版

  • 初期聚合发版是每个子应用各自部署docker镜像,然后通过在nginx配置子应用统一URL去获取子应用的资源。这样的部署方式部署成本大,效率低,难度大。
  • 通过webpack-manifest-plugin把子应用构建的出来的资源生成一份 manifest.json 文件。子应用资源通过版本区分,上传到oss文件服务器。在聚合的时候,基于所有关联子应用版本信息,获取相应的 manifest.json,聚合成一份完整的 manifest.json。在基座应用接受到页面请求时,把相关信息也发送到浏览器。这样方式仅需要部署基座应用,子应用资源直接通过oss来获取。新的部署减少部署成本,提高部署效率,降低部署难度。