微前端技术
近几年一些应用较多的微前端框架及实现方式:从 Single SPA ,qiankun ,Micro-app, module-federation 等。
微前端简单说就是把原来 iframe 实现的隔离机制通过js实现了一遍,背景是为了解决多个项目同时修改一套系统可能带来的管理问题。
微前端的好处在于 iframe 是完全的隔离,而微前端是可控的隔离,在某些情况下可以分享一些内容。可以使前端应用更加灵活可扩展,更好地满足业务需求。
微前端的架构一般是一个基座项目为中心,加上若干子项目组成的。子项目与子项目间是相互独立的,有些内容是可以共享的。比如组件库、公共依赖、缓存管理、权限管理。曾经的 iframe 很难做到这一点。
优点
- 解耦
- 技术栈无关
- 并行开发
- 独立部署
缺点
- 性能问题。
- 一致性。保持不同微前端应用在用户体验、设计和行为上的一致性比较困难。
- 状态共享复杂。
- 复杂性,本身架构带来的复杂性,要管理和协调多个独立的应用。
- 安全性。
JS沙箱
JS沙箱是一种安全机制,可以在不影响全局作用域的情况,限制外部脚本的访问和操作。
实现方式:
- 用 Proxy 对象创建一个沙箱,通过 get 和 set 方法限制不允许访问和修改地全局变量和函数。在安全地范围内通过 get 和 set 进行访问和修改。
function createSandbox(window) {
const sandbox = new Proxy(window, {
get(target, prop) {
// 在这里限制不允许访问的全局变量和函数
if (
prop === 'eval' ||
prop === 'Function' ||
prop === 'window' ||
prop === 'document'
) {
throw new Error(`Access to ${prop} is not allowed in this sandbox.`);
}
return target[prop];
},
set(target, prop, value) {
// 在这里限制不允许修改的全局变量和函数
throw new Error(
`Modification of ${prop} is not allowed in this sandbox.`,
);
},
// // 其他拦截器方法,如has、deleteProperty等
});
}
- 使用iframe 实现沙箱。在一个iframe中加载外部脚本,将外部脚本隔离在一个独立的环境中,避免影 响全局作用域。但是使用iframe会增加网络请求和内存占用开销。
- 使用 Worker 实现。 创建一个 Worker,在独立线程中运行JS代码,将外部脚本隔离在一个独立线程中,避免影响主线程作用域。但是需要考虑线程通信和数据同步的问题。
- 一些沙箱库,比如 sandbox.js、vm.js 等。
CSS隔离
- qiankun 使用 Shadow DOM
- CSS Modules
- postCSS 插件
- tailwind CSS
实现通信机制
- 使用 CustomEvent ,派发和监听自定义事件。避免全局污染,也符合模块化的原则。
- 或者实现一个发布订阅模式,通过emit/on来派发和监听事件。
- 通过路由参数或者 localStorage 来实现。
qiankun
基于 single-spa 的微前端解决方案,通过 js 的 import 功能动态加载子应用,然后在主应用的 dom 中挂载子应用的dom。
-
CSS 隔离 通过 Shadow DOM 实现,是浏览器内置的 web 标准技术,可以创建一个封闭的DOM结构,对外部隔离,包括CSS样式。qiankun挂载子应用,会将子应用的HTML挂载到Shadow DOM上,从而实现CSS隔离。
-
父子项目通信,通信机制
- 观察者模式。通过 setGlobalState 设置 globalState,并通过 onGlobalStateChange 和 offGlobalStateChange 来注册和取消 观察者 函数,从而实现通 信。
-
优缺点
- 提供完备的沙箱方案,包括js沙箱和CSS沙箱。
- 支持静态资源预加载。
- 适配成本高,包括工程化、生命周期、静态资源路径、路由等方面。
- 不支持vite。
wujie
微前端框架,基于 iframe 实现。
应用加载机制和JS沙箱
将子应用的 js 注入到和主应用同域的 iframe 中运行。利用了 iframe 自己的沙箱机制,且有完整的 history 和location。
-
不用注册,不用改造路由,直接使用组件方式
-
一个页面可以同时激活多个子应用,iframe路由不用担心占用问题
-
天然js沙箱,不会污染主应用环境
-
不污染主应用所以销毁子应用也不需要清理
CSS沙箱机制
通过 webcomponent 实现页面样式隔离。 子应用的实例 instance 在 iframe 内运行,dom 在主应用的 webcomponent 中,通过代理iframe的document到webcomponent,实现iframe与webcomponet的互联。
路由同步
劫持子应用所在 iframe 的 history,将子应用的 url 同步到主应用。刷新浏览器初始化 iframe 时,再使用子应用的 replaceState 进行同步。