微前端框架选型

1,179 阅读26分钟

前言

What is Micro Frontends

Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently. -- Micro Frontends 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。

核心价值

  • ~~技术栈无关 ~~

    主框架不限制接入应用的技术栈,微应用具备完全自主权 (已移除)

  • 独立开发、独立部署

    微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新

  • 增量升级

    在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略

  • 独立运行时

    每个微应用之间状态隔离,运行时状态不共享

优点

  • 适用于大规模 Web 应用的开发
  • 更快的开发速度
  • 支持迭代开发和增量升级
  • 拆解后的部分降低了开发者的理解成本
  • 同时具备开发体验 DX(developer experience)和 用户体验 UX(user experience)的开发模式

缺点 / 难点

  • 复杂度从代码转向基础设施

  • 整个应用的稳定性和安全性变得更加不可控

  • 具备一定的学习和了解成本

  • 需要建立全面的微前端周边设施,才能充分发挥其架构的优势

    • 调试工具
    • 监控系统
    • 上层 Web 框架
    • 部署平台

Why Not iFrame

为什么不用 iFrame,这几乎是所有微前端方案第一个会被 challenge 的问题。但是大部分微前端方案又不约而同放弃了 iframe 方案,自然是有原因的,并不是为了 "炫技" 或者刻意追求 "特立独行"。如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。 iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他最大的问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。

  1. URL 不同步,路由状态丢失。浏览器刷新,iframe url 状态丢失、后退前进按钮无法使用。(比较好解决)

  2. DOM 结构不共享,割裂严重。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中。(无法解决)

  3. 全局上下文完全隔离,通信困难。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。 跨源:window.postMessage,可能会有安全问题;同源:共享内存,localstorage等;(比较难解决)

  4. 白屏时间长。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。(睁一只眼闭一只眼)


核心概念

Module Federation

概念

2019 年,Zack Jackson提出Module Federation(模块联邦,以下简称MF),"A game-changer in JavaScript architecture"。MF在构建时处理共享模块,允许在前端应用程序运行时从另一个应用程序资源动态加载代码并共享依赖,彻底解决了代码依赖共享问题与微前端运行时模块化问题,让前端运行时第一次有了和 Node.js 模块系统有类似设计的可能。

实现

MF目前已经被 Webpack,next.js 和rollup所支持。通常在使用 webpack 构建产生的模块都存储在本地,直接被当前应用所使用。在 webpack 5 中提出了远程模块的概念后,允许运行时把当前构建的应用作为容器应用,异步加载远程模块。

对比

从广义的角度出发,模块联邦并非特指Webpack5的模块联邦,而是只要实现了模块的分发、共享,就可以称为“模块联邦”。 实现模块联邦还有一种手段就是SystemJS。表面上看这两者都是在运行时动态加载模块,但内在区别很大:

  1. SystemJS动态加载的模块必须是SystemJS模块或者UMD模块;Webpack5模块联邦则没有这些限制。
  2. SystemJS的模块依赖关系是在运行时确定的,即通过importMap;而Webpack5模块联邦的依赖关系是在编译时确定的,即读取编译时生成的remoteEntry.js来分析依赖。

Webpack5模块联邦要比SystemJS易用的多,唯一存在的问题就是只支持Webpack5项目(vue2的脚手架还不支持webpack5),而SystemJS对Webpack4/5是都支持的。

特点

  • 模块粒度。可以是网络库、公用业务模块、UI 组件、路由、hooks等任何东西。
  • 共享模块 版本化管理。
  • 远程模块不属于当前构建,并在运行时从所谓的容器加载。
  • 一个应用可以是 Host,也可以是 Remote,也可以同时是 Host 和 Remote。
//webpack.config.js
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
​
module.exports = {
  ...
  devServer: {
    port: 8082
  },
  plugins: [
    new ModuleFederationPlugin({
      name:'hostRemoteVar',
      filename:'remoteEntry.js', // 构建出来的文件名
      remotes:{  //可选,表示作为 Host 时,去消费哪些 Remote;
        remote:'remoteVar@http://localhost:8080/remoteEntry.js',
      },
      exposes:{ //可选,表示作为 Remote 时,export 哪些属性被消费;
        './Slides':'./src/Slides'
      },
      shared:['react','react-dom']    
    })
  ]
}

Web Components

组件是前端的发展方向,现在流行的 React 和 Vue 都是组件框架。谷歌公司由于掌握了 Chrome 浏览器,一直在推动浏览器的原生组件,即 Web Components API。相比第三方框架,原生组件简单直接,符合直觉,不用加载任何外部模块,代码量小。目前,它还在不断发展,但已经可用于生产环境,具体浏览器兼容性(以Shadow DOM为例)如下图所示。 狭义的来说,web component是浏览器环境提供的一些新的原生支持的api和模版。广义的说,它是一套可以支持原生实现组件化的技术。 它的三大核心内容:

  • Custom elements:自定义元素,通过使用对应的api,用户可以在不依赖框架的情况下,开发原生层面的自定义元素,最关键的是,它将包含独立的生命周期,以及提供了自定义属性的监听。这就意味着它也同样具备了较高的可操作性。
  • Shadow DOM:影子dom(最大的特点是不暴露给全局),你可以通过对应的api,将shadow dom附加给你的自定义元素,并控制其相关功能。利用shadow dom的特性,起到隔离的作用,使特性保密,不用再担心所编写的代码及样式与其他部分冲突。
  • HTML templates:通过<template/><slot/>去实现内容分发。

参考链接: caniuse.com/?search=Web…


核心实现机制

沙箱隔离

image.png 背景 其实在过去的 Web 应用中是很少提及到沙箱这一概念的,因为组件的开发一般都会由研发通过研发规范来尽可能的去避免组件对当前应用环境造成副作用,诸如:组件渲染后添加了定时器、全局变量、滚动事件、全局样式并且在组件销毁后会及时的清除子应用对当前环境产生的副作用。 与组件完全不同的是微前端是由多个独立运行的应用组成的架构风格,这些系统可能分别来自不同的技术体系。项目的开发、测试从空间和时间上都是分离的,由于没有 Iframe 一样原生能力的隔离很难应用间不发生冲突,这些冲突可能会导致应用发生异常、报错、甚至不可用等状态。

分类 为了保证应用能够稳定的运行且互不影响,需要提供安全的运行环境,能够有效地隔离、收集、清除应用在运行期间所产生的副作用,主要有:全局变量、全局事件、定时器、网络请求、localStorage、Style 样式、DOM 元素。 针对子应用可能产生的副作用类型主要分为两类,

  1. 静态副作用:指的是 HTML 中静态标签内容例如:Script 标签、Style 标签、Link 标签,这些内容属于在 HTML 文档流中就包含的;
  2. 动态副作用:指的是由 JavaScript 动态创建出来的,例如 JavaScript 可以动态创建 Style、动态创建 Script、动态创建 Link、动态执行代码、动态添加 DOM 元素、添加全局变量、添加定时器、网络请求、localStorage 等对当前页面产生副作用的内容。

实现方式

  1. 快照沙箱

顾名思义,在应用运行前通过快照的模式来保存当前执行环境,在应用销毁后恢复回应用之前的执行环境,用于实现应用间副作用的隔离和清除。类似于 “SL 大法”,通过 save 存储环境,通过 load 加载环境的模式。但是它有一个缺点是无法支持多实例。 核心设计思想简述:

  • 针对每一种副作用提供一个 Patch 类,这个类需要提供 save 和 load 两个方法
  • Save 对应着该副作用的环境快照存储,Load 对应着销毁该副作用的销毁恢复环境
  • 并且针对每一种 Patch 还可以存储其在运行期间发生的变化,在优化场景时并不用所有代码,仅恢复执行环境即可
  1. Proxy 代理沙箱 / VM沙箱

通过快照沙箱的最简化的核心实现后可以发现,它的设计理念依赖于整个代码的执行属于线性的过程,即:存储执行环境=>执行具备副作用的代码=>恢复执行环境,但在实际的场景中对于应用的划分并以页面为维度划分,同一个页面可能存在多个应用,所以它的执行顺序并非线性,可能同时存在多个快照沙箱的实例环境,也就是快照沙箱多实例。每个应用都创建一个proxy来代理window,好处是每个应用都是相对独立,不需要直接更改全局window属性。

image.png

目前来说,这两种沙箱需要共存,Proxy 代理沙箱虽然有其优势,但是IE浏览器不支持Proxy;因此一般来说,在代理沙箱不支持的环境中,框架需自动降级到快照沙箱(这就意味着无法多应用共存)。

参考链接: juejin.cn/post/701691… blog.csdn.net/weixin_3908…


主流框架

腾讯 - wujie

无界微前端框架通过继承iframe的优点,解决iframe的缺点,打造一个微前端方案。

image.png

iframe的缺点wujie对应的解决方案
URL 不同步,路由状态丢失浏览器的前进后退可以天然的作用到iframe上,此时监听iframe的路由变化并同步到主应用,如果刷新浏览器,就可以从 url 读回保存的路由
DOM 结构不共享,割裂严重主应用提供一个容器给到shadowRoot插拔,shadowRoot内部的弹窗也就可以覆盖到整个应用 A 存疑
全局上下文完全隔离,通信困难iframe和主应用是同域的,天然的共享内存通信,而且无界提供了一个去中心化的事件机制;
白屏时间长首次白屏wujie实例可以提前实例化,包括shadowRoot、iframe的创建、js的执行,这样极大的加快子应用第一次打开的时间
切换白屏一旦wujie实例可以缓存下来,子应用的切换成本变的极低,如果采用保活模式,那么相当于shadowRoot的插拔

无界微前端框架的几点优势

  • 多应用同时激活在线

    • 框架具备同时激活多应用,并保持这些应用路由同步的能力
  • 组件式的使用方式

    • 无需注册,更无需路由适配,在组件内使用,跟随组件装载、卸载
  • 应用级别的 keep-alive

    • 子应用开启保活模式后,应用发生切换时整个子应用的状态可以保存下来不丢失,结合预执行模式可以获得类似ssr的打开体验
  • 纯净无污染

    • 无界利用iframe和ShadowRoot来搭建天然的js隔离沙箱和css隔离沙箱
    • 副作用局限在沙箱内部,子应用切换无需任何清理工作,没有额外的切换成本
  • 性能和体积兼具

    • 子应用执行性能和原生一致,子应用实例instance运行在iframe的window上下文中,避免with(proxyWindow){code}这样指定代码执行上下文导致的性能下降,但是多了实例化iframe的一次性的开销,可以通过proloadApp提前实例化
    • 包体积只有11kb,非常轻量,借助iframe和ShadowRoot来实现沙箱,极大的减小了代码量
  • 开箱即用

    • 不管是样式的兼容、路由的处理、弹窗的处理、热更新的加载,子应用完成接入即可开箱即用无需额外处理,应用接入成本也极低

相应的也有所不足:

  • 内存占用较高

    • 为了降低子应用的白屏时间,将未激活子应用的shadowRoot和iframe常驻内存并且保活模式下每张页面都需要独占一个wujie实例,内存开销较大。通病
  • 兼容性一般

    • 目前用到了浏览器的shadowRoot和proxy能力,并且没有做降级方案
  • 穿透

    • iframe劫持document到shadowRoot时,某些第三方库可能无法兼容导致穿透

参考链接: zhuanlan.zhihu.com/p/442815952


Single-spa

2018年 Single-SPA诞生了,学习后端的微服务,实现前端的微服务化,让应用、组件以及逻辑都成为可共享的微服务,实现真正意义上的微前端。single-spa 是一个用于前端微服务化的 JavaScript 前端解决方案 (本身没有处理样式隔离, js 执行隔离), 实现了路由劫持和应用加载(即根据不同的路由加载不同的应用)。 Single-spa有不同类别,取决于你在哪里以及怎么使用它们,这是每个single-spa概念上的工作方式:

主题ApplicationsParcelsUtilites
路由有多个路由无路由无路由
API声明式API必要的API导出公共接口
渲染UI渲染UI渲染UI可能也可能不直接渲染UI
生命周期single-spa管理生命周期自定义管理生命周期外部模块:没有直接的single-spa生命周期
什么时候使用核心构建模块仅在多个框架中需要共享通用逻辑时使用
备注最常见的用法Parcels是single-spa的一个高级特性。在对single-spa的注册相关api有更多了解之前,请尽量避免使用该特性。一个single-spa 的 parcel,指的是一个与框架无关的组件,由一系列功能构成,可以被应用手动挂载,无需担心由哪种框架实现。最适合在框架之间共享UI部分。最适合共享通用逻辑

single-spa不能解决如何托管、构建或部署代码的问题,提供了一些策略供参考:

MonorepoNPM包动态加载模块
搭建难度简单中等困难
代码是否独立NoNoYes
分开构建NoYesYes
分别部署NoYesYes
例子- simple-webpack-example - single-spa-examples- single-spa-login-example-with-npm-packages- SystemJS example
备注一个代码仓库, 一个build包1. Web服务器:在你的web服务器为每个子应用的正确版本创建一个动态脚本。 2. 使用模块加载 例如 SystemJS 可以在浏览器通过动态urls下载并执行JavaScript代码。

single-spa 生态系统正在迅速发展,支持尽可能多的框架和构建工具,比如single-spa-vue是一个针对vue项目的初始化、挂载、卸载的库函数,可以实现single-spa注册的应用、生命周期函数等功能。此外,single-spa拥有检测工具,一个Firefox/Chrome的浏览器扩展工具,用于提供single-spa开发过程中的一些工具。

参考链接: single-spa.js.org/ github.com/single-spa/… zh-hans.single-spa.js.org/docs/gettin…


阿里 - qiankun

qiankun 孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台,在经过一批线上应用的充分检验及打磨后,将其微前端内核抽取出来并开源。

特点:

  • 基于 single-spa 封装,提供了更加开箱即用的 API。
  • 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
  • HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
  • 样式隔离,确保微应用之间样式互相不干扰。
  • JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
  • umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。

我们从2020年年初关注到它,但是当时的选择不是它,而是选择自行搭建微应用的方式,原因大体如下:

  1. 搭建demo中&社区反馈了许多问题,项目压力,时间紧张,此方案具有一定的不确定性;
  2. 无法兼容IE
  3. 无法满足多应用共存
  4. 沙箱能力不够成熟

以上是当时的1.x版本,而qiankun** 2.x **带来了很多变化:

  1. 定位

将由 微前端框架 转变为 微应用加载器。此前 qiankun 的典型应用场景是 route-based 的控制台应用,做为一个微应用的聚合框架而被使用。 在简单场景下,一个负责聚合与切换的主应用 与 多个相互独自的微应用 一起构成了整个大的微前端应用,一般来说页面上活跃着的也往往只有一个微应用。 在另外一些场景下,可以在同一个页面中,加载多个不同的微应用,每个微应用都是主应用的组成部分 或者是 提供一些增强能力,这种场景可以说是微应用粒度的前端组件化。 因此,qiankun@2.0 跳出 route-based 的微前端场景, 提供更加通用的微应用加载能力,让用户可以更加自由的组合微应用来搭建产品。

  1. 重大功能
  • 支持多应用并行及多实例沙箱

qiankun@1.x 中,沙箱、样式隔离等机制只能对单一微应用场景生效,多个微应用共存的支持能力尚不完备。 而在 2.0 版本中,默认情况下沙箱可以确保单实例场景子应用之间的样式隔离,但是无法确保主应用跟子应用、或者多实例场景的子应用样式隔离。 当配置为 strictStyleIsolation: true 时,表示开启严格的样式隔离模式。这种模式下 qiankun 会为每个微应用的容器包裹上一个 shadow dom 节点,从而确保微应用的样式不会对全局造成影响。基于 ShadowDOM 的严格样式隔离并不是一个可以无脑使用的方案,大部分情况下都需要接入应用做一些适配后才能正常在 ShadowDOM 中运行起来,使用者需要清楚开启了 strictStyleIsolation 意味着什么。 除此以外,qiankun 还提供了一个实验性的样式隔离特性,当 experimentalStyleIsolation: true时,qiankun 会改写子应用所添加的样式为所有样式规则增加一个特殊的选择器规则来限定其影响范围。

  • 支持手动 加载/卸载 微应用

提供了一个全新的 API loadMicroApp ,用于手动控制微应用的加载、卸载时机。

  • 支持 IE11 沙箱兼容

qiankun 1.x 在 IE 使用的主要阻碍就是 qiankun 的沙箱使用了 ES6 的 Proxy,而这无法通过 ployfill 等方式弥补。这导致 IE 下的 qiankun 用户无法开启 qiankun 的沙箱功能,导致 js 隔离、样式隔离这些能力都无法启用。 为此,2.x实现了一个 IE 特供的快照沙箱,用于这些不支持 Proxy 的浏览器;这不需要用户手动开启,在代理沙箱不支持的环境中,会自动降级到快照沙箱。 注意,由于快照沙箱不能做到互相之间的完全独立,所以 IE 等环境下不支持多应用场景, singlur 会被强制设为 true。

  • 官方的极简微应用通信方案

通过initGloabalState等API来实现简单场景下的应用间通信。

  • 支持基于 Shadow DOM 的样式隔离

样式隔离也是微前端面临的一个重要问题,在 qiankun@1.x 中,支持了微应用之间的样式隔离(仅沙箱开启时生效),这尚存一些问题:

  1. 主子应用之间的样式隔离依赖手动配置插件处理
  2. 多应用场景下微应用之间的样式隔离亟待处理

为此,2.x引入了一个新的选项, sandbox: { strictStyleIsolation?: boolean } 。在该选项开启的情况下,我们会以 Shadow DOM 的形式嵌入微应用,以此来做到应用样式的真正隔离。 但是开启 Shadow DOM 也会引发一些别的问题

一个典型的问题是,一些组件可能会越过 Shadow Boundary 到外部 Document Tree 插入节点,而这部分节点的样式就会丢失;比如 antd 的 Modal 就会渲染节点至 document.body ,引发样式丢失;针对刚才的 antd 场景你可以通过他们提供的 ConfigProvider.getPopupContainer API 来指定在 Shadow Tree 内部的节点为挂载节点,但另外一些其他的组件库,或者一些代码也会遇到同样的问题,需要额外留心。 此外 Shadow DOM 场景下还会有一些额外的事件处理、边界处理等问题,官方会逐步更新文档指导用户更顺利的开启 Shadow DOM。所以要根据实际情况来选择是否开启基于 shadow DOM 的样式隔离,并做好相应的检查和处理。

  1. 锦上添花
  • 升级 single-spa 到 5.x 版本
  • 更灵活的 prefetch 的定制策略
  • 配套的 webpack 插件
  • 更友好的部署场景支持,如自动为微应用注入运行时 publicPath 等
  • 更简单易懂的 API,重构了许多代码,使其更清晰和更具扩展性
  • 修复了一些 bug

参考链接: qiankun.umijs.org/ juejin.cn/post/687114…


字节跳动 - Garfish

目前的 Garfish 作为字节跳动各部门应用最广泛的微前端解决方案已经服务超过 100+ 前端团队,400+ 项目;另外字节跳动的现代 Web 工程体系也已开源(Modern.js),深度集成 Garfish 提供了对微前端的原生支持,提供更开箱即用的能力。但目前字节的现代 Web 研发体系建设,有意收敛和围绕着 React 来进行。

架构设计

框架特性

  • 丰富高效的产品特征

    • Garfish 微前端子应用支持任意多种框架、技术体系接入
    • Garfish 微前端子应用支持「独立开发」、「独立测试」、「独立部署」
    • 强大的预加载能力,自动记录用户应用加载习惯增加加载权重,应用切换时间极大缩短
    • 支持依赖共享,极大程度的降低整体的包体积,减少依赖的重复加载
    • 内置数据收集,有效的感知到应用在运行期间的状态
    • 支持多实例能力,可在页面中同时运行多个子应用提升了业务的拆分力度
    • 提供了高效可用的调试工具,协助用户在微前端模式下带来的与传统研发模式不同带来的开发体验问题
  • 高扩展性的核心模块

    • 通过 Loader 核心模块支持 HTML entry、JS entry 的支持,接入微前端应用简单易用
    • Router 模块提供了路由驱动、主子路由隔离,用户仅需要配置路由表应用即可完成自主的渲染和销毁,用户无需关心内部逻辑
    • Sandbox 模块为应用的 Runtime 提供运行时隔离能力,能有效隔离 JS、Style 对应用的副作用影响
    • Store 提供了一套简单的通信数据交换机制

Modern.js Modern.js 开源项目是刚起步的状态,最新发的 1.0 版是公测状态。当前版本还没有包含 Roadmap 上一些重要功能,字节计划以每周发版的节奏,把这些功能补上。

image.png

参考链接: mp.weixin.qq.com/s/L9wbfNG5f… juejin.cn/post/702111… modernjs.dev/ juejin.cn/post/701691… zhuanlan.zhihu.com/p/386607009


欢聚时代 - EMP

image.png

image.png

特点:

  • 基于webpack5 Module Federation (模块联邦)
  • 去中心化

实现方式:

  • Lerna + NPM 解决依赖共享、依赖更新、调试、构建、发布等问题
  • Typescript 类型检测 提升安全性;代码规范 提升代码质量;团队开发增益 IDE的⽀持更好,减少⽂档、⼝⼝相传、代码回顾等的依赖
  • EMP-CLI 脚本工具

实战项⽬:

  • PK条
  • Coco2d游戏
  • YY PC客户端
  • 欢聚变⾊⻰

参考链接: github.com/efoxTeam/em… juejin.cn/user/483440… 1.0 vs 2.0 :juejin.cn/post/705149…


铃盛 - Fronts

Fronts 是一个基于 Webpack 的 Module Federation API 设计的渐进式微前端框架。它强调颗粒间的去中心化依赖管理,并支持多种运行模式来满足不同的微前端架构需求。

image.png

image.png

  • 支持非 Module Federation - 虽然 Fronts 基于 Module Federation 概念, 但它依然支持任何传统且不支持 Module Federation 的前端应用。
  • 去中心化配置 - 只需要在每个 Fronts 应用中设置 site.json,就像设置一个 package.json 一样简单,Fronts 支持多层嵌套的微前端。
  • 跨框架 - 没有任何现代前端框架限定。
  • 代码分割/懒加载 - 支持在 Fronts 应用内进行代码拆分和导出共享模块,它可以被其他 Fronts 应用作为依赖模块进行懒加载。
  • CSS 隔离 - 可选的 CSS 隔离设定,并根据不同的渲染方式有宽松隔离和严格隔离的可选项。BEM 、CSS Module 、CSS-in-JS (styled-components)
  • 生命周期 - 每个 Fronts 应用的 Entry 支持简洁的生命周期接口。
  • Web Components 和 iFrame - 支持多种前端运行时容器用于不同隔离环境要求。
  • 多种构建模式 - 同时支持在微前端模式和非微前端模式构建,兼容动态化的运行时集成和静态化的构建时集成。
  • Monorepo 和 TypeScript - 良好支持 Monorepo 和 TypeScript,它们和 Fronts 是非常适合架构在一起的技术栈。
  • 版本控制 - Fronts 提供的版本控制可用于高效和动态的即时交付应用,当然也包括支持灰度发布。
  • 零劫持 - Fronts 不做任何执行容器上的环境全局公共 API 劫持, 保持运行环境的原始性,避免可能带来性能损失和安全问题。
  • 通用化消息通讯 - Fronts 提供简洁通用的响应式 API, 它支持前端绝大部分原生 API。

Demo:

image.png

image.png

image.png

参考链接: fronts.js.org/ github.com/unadlib/fro…


总结

框架对比

下表为个人理解并归纳的,有一定主观成分,若有不同见解请一起讨论~

维度wujiesingle-spaqiankunGarfishEMPFrontsOne-for-all备注
iframe路由驱动依赖引用
发展历程2021.12 发布技术文章18年起,目前已经是5.x了;生态完善;19年起,目前版本是2.6.3,已在蚂蚁内部服务了超过 200+ 线上应用;社区活跃;21.9,发布alpha版本,目前最新是1.4.219年起,20+个版本迭代,目前最新是2.1.0;主要是内部使用19年起;主要是内部使用;19年起;bs内部;
可用/易用性不开源; 但易用;开源; 但是对项目的改造太多,对项目的可维护性带来了严峻挑战。开源; 少数配置;开源;开源;开源; 少数配置;--
star数--10.9k12.2k1.4k1.7k0.5k--
技术栈限制
浏览器兼容性不兼容IE,只支持现代浏览器Chrome、 Firefox、 Safari、 IE11和 Edge可兼容IE,但IE 环境下(不支持 Proxy 的浏览器)只能使用单实例模式------取决于子应用的兼容性
依赖共享可选可选可选有利(减小体积) 有弊(依赖必须一致)依赖是否共享,影响了整体体积,也影响了是否可以同时使用不同版本的依赖
独立部署多种策略供选择
集成模式运行时可选运行时运行时构建时运行时构建时
js隔离iframe和ShadowRoot,天然的js隔离沙箱和css隔离沙箱未实现是 借鉴qiankun的设计--window快照记录与恢复定义规范CSS 的隔离是在所难免,这也被不少微前端框架所支持。而 JS 隔离实现成本相对就高了不少,需要异步请求到这个 JS 文件(甚至是跨域),并针对各种可能访问的全局接口进行全面的劫持代理,既要保证安全性、性能和稳定性,还要考虑不同浏览器的兼容性等方面,其实往往得不偿失,尤其是现代前端工程中甚少全局污染,事实上这样的隔离是否是非常必要,也取决于落地在每个微前端颗粒中的实际情况。如果是外部不可控风险的颗粒,我们往往可以少量地使用 iFrame 来做到真正的 sandbox 隔离,通过约定接口的方式进行交互。而在大多数可控的微前端颗粒中,事实上我们仅仅需要非隔离方式进行在同一个 JS 运行容器上直接地相互访问,这是高效便捷的。
css隔离是 但有一定局限性定义规范定义规范定义规范
子应用保活是 多个容器 + loadMicroApp--在多tab页切换之后,子应用状态能保留,不丢失
多应用共活是 多个iframe是 activeRule--在同一个页面上,多个子应用同时激活
拆分粒度应用可选应用应用模块模块应用应用 > 模块
模块间/主从 应用通讯全局变量APIAPIAPI--APIvuex
备注共享模块,业务划分独立

参考链接: martinfowler.com/articles/mi… segmentfault.com/a/119000003…

结论

倾向于 qiankun

补充:本文写于2022年3月,迄今为止,wujie已经开源。