- 微前端概念
微前端是一个主应用中,包含多个子应用的架构。因此iframe 也是一种微前端方案
- 什么情况下,可以考虑使用微前端
- 应用太过于庞大,每次构建和部署都需要很长时间
- 想渐进式重构旧的系统,可以用微应用的方式,对部分业务做重构
- 当公司有多个前端团队,每个团队负责不同的业务线或产品功能的时候,也可以使用微前端的技术架构
-
ifame 作为微前端方案的一些问题:
- UI 不同步,比如iframe 中有一个弹框,需要在主界面中居中,就会比较难以实现。
- 加载缓慢,每次都需要重新加载资源,没有预加载的过程,也不能复用已经加载过的资源
- 主应用和iframe 子应用之间,数据完全隔离,不能共享,因此存在着子应用的免登问题,数据实时同步的问题。
- 每次刷新页面,iframe的url都会丢失,而且前进后退按钮没办法用。
-
qiankun 自动加载的流程
qiankun 使用了 import-html-entry 这个包来做处理。
- qiankun 会用 原生fetch方法,请求微应用的 entry 获取微应用资源,然后通过 response.text 把获取内容转为字符串;
- 将 HTML 字符串传入 processTpl 函数,进行 HTML 模板解析,通过正则匹配 HTML 中对应的 javaScript(内联、外联)、css(内联、外联)、代码注释、entry、ignore 收集并替换,去除 html/head/body 等标签,其他资源保持原样;
- 将收集的 styles 外链URL对象通过 fetch 获取 css,并将 css 内容以 的方式替换到原来 link标签的位置;
- 收集 script 外链对象,对于异步执行的 JavaScript 资源会打上 async 标识 ,会使用 requestIdleCallback 方法延迟执行;
- 接下来会创建一个匿名自执行函数包裹住获取到的 js 字符串,最后通过 eval 去创建一个执行上下文执行 js 代码,通过传入 proxy 改变 window 指向,完成 JavaScript 沙箱隔离;
- 由于 qiankun 是自执行函数执行微应用的 JavaScript,因此在加载后的微应用中是看不到 JavaScript 资源引用的,只有一个资源被执行替换的标识;
- 当一切准备就绪的时候,执行微应用的 JavaScript 代码,渲染出微应用
-
qiankun 方案和single-spa方案的区别:
-
qiankun 方案 在single-spa 架构的基础上,做了如下处理:
-
改手动加载为自动加载。
single-spa 方式
registerApplication({ name: "@polyglot-mf/navbar", app: () => System.import("@polyglot-mf/navbar"), activeWhen: "/", }); registerApplication({ name: "@polyglot-mf/clients", app: () => System.import("@polyglot-mf/clients"), activeWhen: "/clients", });
qiankun 的方式
import { registerMicroApps, start } from 'qiankun'; registerMicroApps([ { name: 'vue app', entry: '//localhost:7100', container: '#container-vue', activeRule: '/micro-vue' }, { name: 'react app', entry: '//localhost:7101', container: '#container-react', activeRule: '/micro-react' }, ]); start();-
qiankun 提供了CSS和JS 的样式隔离方案,但single-spa 没有实现,需要自己去解决。
-
qiankun 的css 样式隔离方案
qiankun 提供了基于
shadowDOM实现的样式隔离以及使用postcss 的方式的样式隔离-
qiankun 的JS隔离方案
基于ES6的proxy,基于原始window伪造了一个新的window对象,同时借助Proxy对象定义了该伪造window的基本操作的行为,包括:set、get等等。
-
-
qiankun 的JS隔离方案
- iframe 方案
- qiankun 中三类沙箱
LegacySandbox:单实例代理沙箱,简单来讲就是只存在一个window实例,所有的操作都是对这一个实例的操作。(使用了Proxy的方式来代理window 对象)ProxySandbox:多实例代理沙箱,通过对window的拷贝建立多个副本,在沙箱中对建立的副本进行操作.(使用proxy 的方式来代理window 的拷贝对象)SnapshotSandbox:快照沙箱,基于 diff 方式实现的沙箱,用于不支持 Proxy 的低版本浏览器。(基于快照的方式)
-
qiankun 方案的一些缺点
-
父子应用存在样式污染。父应用的样式,也会在子应用生效,子应用也可以在父应用生效。
-
运行时越界, 假如使用qiankun 中的CSS隔离的方法,使用
{ sandbox : { strictStyleIsolation: true } },或者 添加experimentalStyleIsolation: true属性。例如 body 构建 DOM 的场景(弹窗、抽屉、popover 等这种插入到主应用body 的dom 元素),必定会导致构建出来的 DOM 无法应用子应用的样式的情况,目前框架会开放API去改挂载的节点或者挂载的类名。
-
- 无界的方案
使用iframe + Web Components 的方式来实现
JS 运行在iframe中, DOM结构使用shadowDOM的方式,运行在主应用中