1、微前端的实现方案
基于 qiankun 的微前端实践
微前端(Micro-Frontends)是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。
微前端目标直指巨石应用业务难题,旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用 (Frontend Monolith) 后,随之而来的应用不可维护的问题
isMicroApp 的变量可以控制启动微前端渲染还是独立 APP 渲染,这个实际是 qiankun 客户端启动后,会在 window 上挂在 __POWERED_BY_QIANKUN__ 变量标识运行时环境。
qiankun 的渲染过程:微应用的 JS CSS 文件请求是属于 Ftech/XHR 类型,说明 js 文件的请求是 qiankun 客户端自行构造的。至于为何要这么做?我的理解是为了实现微前端的沙箱功能。
这里必然要涉及前端的跨域问题,尤其是当主应用和微应用的域名不一致时,qiankun 客户端如何能够在跨域的限制之下获取到微应用的页面资源?
在 qiankun 的框架下,一个页面集成到另外一个页面系统中,最关键的核心点就是将微应用封装成具有生命周期的页面组件,使得 qiankun 可以调用 React 或者 Vue 的 render 能力,将页面渲染到对应的 DOM 节点。
qiankun 的核心概念
第一步则是注册路由,确定微前端启动的时机和启动渲染的内容(when 和 where)。
主流的沙箱模式是通过创建一个独立的作用域隔离作用域链,同时克隆全局变量来实现的,但是这种隔离 + 克隆方案并不完美,在复杂运行场景中,无论性能还是安全性都是难以保证的,特别是 CSS 的隔离。
无界微前端
模块联邦在微前端架构中的实践
为什么是Webpack模块联邦?
当我们研究了所有的替代方案后,出于以下原因,选择Webpack模块联邦更有意义。
-
没有维护成本(如果你自己建立一个架构,会有维护成本)
-
没有团队特定的学习成本(如果你自己建立一个架构,会有学习成本)
-
向模块联邦过渡的成本很小
-
不需要对每个项目进行重新架构
-
所有的需求都在构建时得到满足
-
在运行时不需要额外的工作
-
分享依赖的成本低
-
库/框架独立
-
你不需要处理所有的压缩和缓存问题
-
你不需要处理路由问题
-
Shell和Micro Apps不是紧耦合的,而是松耦合的
模块联邦的两个伟大的功能了 :)
expose:它允许你从任何应用程序到另一个应用程序共享一个组件、一个页面或整个应用程序。你所暴露的一切都被创建为一个单独的构建,从而创造了一个自然的tree shaking
。每个构建都以文件的MD5哈希值命名,所以你不必担心缓存的问题。
remote: 它决定了你将从哪些应用程序接收一个组件、一个页面或应用程序本身。 每个应用程序都可以同时暴露和定义一个远程,并多次进行。
介绍 - qiankun
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
- 💪 HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
- 🛡 样式隔离,确保微应用之间样式互相不干扰。
- 🧳 JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
- ⚡️ 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
微前端架构具备以下几个核心价值:
-
技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权 -
独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新 -
增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
-
独立运行时
每个微应用之间状态隔离,运行时状态不共享
qiankun 的诸多设计均是秉持这一原则,如 HTML entry、沙箱、应用间通信等。这样才能确保微应用真正具备 独立开发、独立运行 的能力。
qiankun 会在跑子应用之前在 window 沙箱设置 POWERED_BY_QIANKUN 的变量,如果有这个变量就不要直接渲染,在 mount 生命周期里做渲染,否则就直接渲染。
还要指定静态资源的加载地址,通过 webpack_public_path 的全局变量。
Why Not Iframe
为什么不用 iframe,这几乎是所有微前端方案第一个会被 challenge 的问题。但是大部分微前端方案又不约而同放弃了 iframe 方案,自然是有原因的,并不是为了 "炫技" 或者刻意追求 "特立独行"。
如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。
iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
1url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
2UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..
3全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
4慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。
其中有的问题比较好解决(问题1),有的问题我们可以睁一只眼闭一只眼(问题4),但有的问题我们则很难解决(问题3)甚至无法解决(问题2),而这些无法解决的问题恰恰又会给产品带来非常严重的体验问题, 最终导致我们舍弃了 iframe 方案。
主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start
即可。
Shadow DOM 接口是关键所在,它可以将一个隐藏的、独立的 DOM 附加到一个元素上。
在单实例模式下,你可以使用 excludeAssetFilter
参数来放行这部分资源请求,但是注意,被该选项放行的资源会逃逸出沙箱,由此带来的副作用需要你自行处理。
如何解决拉取微应用 entry 时 cookie 未携带的问题
fetch() - Web API 接口参考 | MDN
1: mode: 'cors' 开启跨域资源共享
2:credentials: 'include', 在当前域名内自动发送 cookie
SanpshotSandbox和LegacySandbox沙箱,都是 单例模式 下使用的沙箱。也即一个页面中只能同时展示一个微应用,而且无论是 set 还是 get 依然是直接操作 window 对象。
在这样单例模式下,当微应用修改全局变量时依然会在原来的 window 上做修改,因此如果在同一个路由页面下展示多个微应用时,依然会有环境变量污染的问题。
import-html-enry
qiankun 框架配套开发支持 html 作为入口(entry) 的资源加载器(loader)。
工作环境:
- qiankun 框架为了解决 JS Entry 的问题,采用更方便的 HTML Entry 方式,目的让微应用接入像 iframe 一样只需配置页面 html 的 url 地址
2、项目中采用的方案
3、微前端中主子应用数据管理和通信的实现
4、沙箱隔离,沙箱的实现原理JS沙箱和样式沙箱
5、表单生成器的实现和其他方案对比?
6、其他印象比较深的项目和重难点,以及收获
7、