Skip to content

Latest commit

 

History

History
95 lines (58 loc) · 5.34 KB

微前端.md

File metadata and controls

95 lines (58 loc) · 5.34 KB

微前端

什么是微前端

微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略

微前端的特点

  • 技术栈无关
  • 独立开发、独立部署
  • 增量升级
  • 独立运行时(微应用之间状态隔离、运行时状态不共享)

qiankun初始化全局配置 - start

  1. 给 window 设置 __POWERED_BY_QIANKUN__ 属性,在应用中用来判断是否是在主应用容器中运行
  2. 检查 prefetch 属性,如果需要预加载,则添加全局事件 single-spa:first-mount 监听,在第一个子应用挂载后加载其他子应用的资源,优化后续其他子应用加载的速度
  3. 根据 singluarMode 参数设置是否为单实例模式(单实例模式下,新的子应用的挂载必须是在旧的子应用卸载后)
  4. 根据 jsSandbox 参数设置是否启用沙箱运行环境
  5. 调用 single-spa 的 startSingleSpa 方法启动应用

qiankun是如何注册应用的

  1. 已经注册过的子应用不需要再次注册,过滤掉已注册的内容
  2. 核心注册实现还是调用 single-spa 的 registerApplication 方法
  3. 设置子应用属性,name子应用名称,callback激活时的回调,activeRule激活规则,props传递给子应用的参数

qiankun是如何加载应用的

  1. 获取子应用的 entry 和 name
  2. 根据子应用的 name 生成唯一的ID
  3. 获取子应用传过来的一些配置(是否开启沙箱等)
  4. 根据 entry 获取子应用的入口(可能是html,也可能是js)
  5. 获取子应用的渲染内容
  6. 处理子应用的样式(通过 shadow dom 实现样式隔离)
  7. 设置子应用的渲染容器
  8. 获取子应用的 render 函数,执行 render 函数

qiankun是如何获取子应用资源

  1. 通过 import-html-entry 库,根据 entry 进入加载之应用
  2. 返回一个对象,包含:将脚本内容注释后的模板,资源地址根路径,获取外部引入的脚本文件的方法,获取外部引入的样式表文件的方法,执行模板文件中所有 JS 脚本文件的方法(可以指定脚本的作用域)

qiankun是如何进行沙箱隔离的

  1. 首先会判断浏览器是否支持 Proxy
  2. 如果支持 Proxy 使用的是 LegacySandbox 或 ProxySandbox,区别是 LegacySandbox 是单实例,ProxySandbox 是多实例
  3. 如果不支持 Proxy 使用的快照沙箱

LegacySandbox 本质是利用 Proxy,在子应用中运行过程中,通过 两个 map 对象来分别记录新增的全局变量和修改的全局变量(addedPropsMapInSandbox,modifiedPropsOriginalValueMapInSandbox),还有一个 map 对象来记录所有操作过的全局对象(currentUpdatedPropsValueMap)。 在沙箱关闭时,通过 addedPropsMapInSandbox 删除子应用运行时新增的所有全局变量,通过 modifiedPropsOriginalValueMapInSandbox 还原子应用运行时修改过的全局变量

总结:LegacySandbox 是利用快照实现沙箱隔离的(首先背会,沙箱关闭时还原到之前的状态)

LegacySandbox 本质也是利用 Proxy,但是会把子应用运行时的所有对全局的设置代理到 updateValueMap 上,对于全局对象的取值会优先从 updateValueMap 上取,如果没有则从 window 上取,如果取的是非构造函数之外的函数,返回的函数是通过bind绑定this到window的函数

总结:ProxySandbox 是代理沙箱

挂载沙箱

genSandbox 函数不仅返回了一个 sandbox 沙箱,还返回了 mount 和 unmount 方法,分别在子应用挂载时和卸载时调用

mount 方法首先调用沙箱的激活方法,然后劫持了计时器,window事件监听,window.history事件监听,动态添加 head 元素事件

在子应用运行时,会开启定时器,在子应用卸载的时候,应该将这些定时器销毁,同样的 事件和 history 事件的处理与定时器类似;

卸载沙箱

首先对挂载沙箱时,定义的计数器,绑定的事件的移除 调用沙箱的卸载方法

qiankun是如何进行子应用之间通信的

  1. Actions 通信

Actions 通信,本质是观察者模式,在主应用中通过 initGlobalState 定义好全局状态,同时可以通过 action.onGlobalStateChange 注册观察者,同样的子应用在 mount 生命周期中可以通过 props.onGlobalStateChange 注册观察者,然后修改状态是通过 setGlobalState 来修改状态,状态修改后,注册的所有观察者都可以拿到变更前的状态和变更后的状态

缺点:

  • 子应用独立运行时,需要额外的配置无 Actions 的逻辑
  • 子应用需要先了解状态池的细节,在进行通信
  • 由于状态池无法跟踪,通信场景较多时,容易出现状态混乱,维护困难等问题
  1. Shared 通信

Shared 通信的原理是,主应用基于 redux 维护一个状态池,通过 Shared 实例暴露一些方法给子应用使用(比如获取状态、设置状态)。同时,子应用需要单独维护一份 shared 实例,在独立运行时,使用自己的 shared 实例,在嵌入子应用时使用主应用的 shared 的实例。

子应用是如何判断使用自己的 shared 实例还是使用主应用的 shared 实例呢?

子应用的 Shared 类中,定义一个重载 shared 实例的方法,当主应用有传递 shared 实例的时候,就用主应用的 shared 实例重载自己的 shared 实例。

qiankun是如何进行预加载的