近期又开始帮团队同学看基座的一些问题,突然想起之前记录的微前端原理,复习&水一篇文章
- 入口
- new Garfish
微前端子应用的生命周期为
- 渲染阶段
- 若入口类型为 HTML 类型,将开始解析和拆解子应用资源
- 若入口类型为 JS,创建子应用的挂点 DOM
- 主应用通过路由驱动或手动挂载的方式触发子应用渲染
- 开始加载应用的资源内容,并初始化子应用的沙箱运行时环境
- 判断入口类型
- 将子应用存在”副作用“(对当前页面可能产生影响的内容)交由沙箱处理
- 开始渲染子应用的 DOM 树
- 触发子应用的渲染 Hook
- 销毁阶段
- 若路由变化离开子应用的激活范围或主动触发销毁函数,触发应用的销毁
- 清除应用在渲染时和运行时产生的副作用
- 移除子应用的 DOM 元素
最重要的几个节点
- 加载器(Loader)
- HTML 入口类型,拆解 HTML Dom、Script、Style
- JS 入口类型,提供基础 Dom 容器
- 负责注册平台侧提供的应用列表
- 负责加载和解析子应用入口资源
- 预加载能力
- 解析子应用导出内容
- 沙箱隔离(Sandbox)
- 提供代码执行能力,收集执行代码时存在的副作用
- 提供销毁收集副作用的能力
- 支持沙箱多实例,收集不同实例的副作用
- 路由托管(Router)
- 解决不同应用间的路由不同步问题
- 提供路由劫持能力,在主应用上管控子应用路由
- 提供路由驱动能力来拼装完整的平台的能力
- 子应用通信(Store)
- 建立通信桥梁
- 提供共享机制
资源加载
loader实现
资源加载都是先通过fetch下载源代码,然后根据不同文件类型进行处理。 常见的有html、js、css的loader
- html loader 在fetch下载html文本后,通过document.createElement('html').inner(code)来生成node树,然后遍历树节点来获取特定的元素(如meta link style script),然后再加载这些js和css资源的内容
- css loader 下载css文件后,在需要渲染template的时候创建style元素,将内容注入进style
- js loader 下载js文件后,包裹new Function,注入proxyEnv,再eval执行
provider查找
微前端的子模块需要提供provider函数给底层进行执行,那我们在加载众多资源后如何才能找到这个provider函数呢?
参考umd的打包代码,会将入口文件的exports属性赋值给module.exports或者window
那么我们可以自定义一个exports对象去接收,或者在window上查找provider函数
沙箱隔离
snapshot快照模式
-
activate和deactivate时是触发patchLists里不同的对比方法
-
全局变量patch。主要维护了原始对象、变更对象,拿原始对象的属性和目标对象对比,进行增加和删除,同时存储下变更
-
style patch 通过对比document.head下的节点,来进行变更和还原
-
event patch 代理window的addEventListener和removeEventListener函数,内部维系一个event注册map
-
interval patch 和event同理,代理+内部维护map
-
其他patch history、webpackJsonp都是代理
vm虚拟机模式
snashot还是会存在污染window变量的问题,同时无法保证同时存在多个子应用之间的隔离 vm模式主要是通过proxy,将一个对象作为window的proxy,同时也对event、storage、timer、history等api进行代理 然后通过 new function(window,this)(proxyWindow)的方式运行,完成代码环境隔离
路由托管
路由的切换通常是通过pushState、replaceState方法,以及popState和hashchange事件来实现 所以可以对pushState、replaceState方法进行重写 && popstate hashchange事件进行代理,dispatch一个私有event,进行router的自管理
应用通信
参考eventEmitter
Garfish介绍见 mp.weixin.qq.com/s/L9wbfNG5f…