关于微前端架构


我们先给微前端做一个简明的定义:多个团队相对独立(技术选择,代码库,发布流程)地发布应用功能来公共构建 Web 应用的架构方式。 正如下方引用的内容所说的一样:

In short, micro frontends are all about slicing up big and scary things into smaller, more manageable pieces, and then being explicit about the dependencies between them. Our technology choices, our codebases, our teams, and our release processes should all be able to operate and evolve independently of each other, without excessive coordination.

Micro Frontends

为什么需要微前端

为了更加全面地了解微前端在实际应用中的价值,我们可以尝试从两个不同的角度来进行分析,一是微前端能够给我们的项目带来什么收益,二是在什么情况下需要或者适合引入微前端架构来解决问题。

微前端的所有收益应该都是相对独立这个特性带来的:

  1. 简单且解耦的运行时和代码库

    每个子应用独立,运行时状态和代码库都彼此隔离,意味着更加简单清晰,通过某些约定好的通信协议来进行交互,跨业务和团队的耦合更低。

  2. 增量升级

    由于独立和隔离的特性,每个子应用可以适时进行重构和技术升级,对于整个团队和应用来说,即是可以实现渐进式的重构,逐步解决历史的技术债务。

  3. 独立开发,测试,发布

    每个子应用可以有自己的研发流程控制,以更好地配合自身业务特性。

  4. 团队自治

    结合上述的三点,在技术实现和组织架构上,单个子应用的团队拥有更多的自治权,这对于业务自主性和团队凝聚力上都能有更多的帮助。

那什么情况下需要或者适合引入呢?

那一定是上述这些收益可以解决你项目中遇到的问题时,我们分两种场景来说明一下,一个是创建一个新应用,一个是维护和迭代旧应用。

  • 新应用

    在创建新应用时,基本可以说,绝大部分情况你都暂时不需要。除非你的应用研发团队,单单前端的规模达到超过两个披萨可以喂饱的人数,并且业务形态可以拆分为多个边界相对清晰的子业务,不同的子业务可能对于研发流程和节奏上会有不同诉求。

    可能有人会说,我要有前瞻性,未来我的应用可能就是符合上述条件了。那么这个未来有多久呢(如果明确判断半年那可以考虑下的)?引入微前端也是有成本的,技术选择是更多是适合当下且能适应接下来一段时间的变化,尽量不要没有问题时假设问题。

  • 旧应用

    那么在旧应用的迭代和维护上,首先满足一个条件,这个应用是个相对大型的应用。这个时候当你需要去解决一些维护上的问题时,如长时间积累的技术债务需要一步步重构升级解决,或是组织架构调整导致的应用内不同模块的维护方式或者迭代节奏不同等,我们可以考虑去引入微前端架构。

    最典型的就是各种 “aaS” 的控制台应用。

这里放一个简单的流程图,可以在判断是否需要微前端架构时提供参考:

need micro frontends

不同的实现方案

微前端的实现,最重要的有两部分,即隔离和整合,实现多个子应用的独立,并将其整合在一起形成整体,下边列举相关的一些方案并尝试说明其特性:

服务端组合

通过一个中心服务去请求多个不同子应用的服务,将子应用的页面组合到一起来实现微前端的架构。

Nginx 上可以使用 SSI 指令来实现页面嵌入。

整合是没有问题了,但是在子应用的隔离上并没有实现得很好,运行时都是同一个,也就是 JS & CSS 会相互影响。当然可以通过一些方案来解决,但是既要在服务端去改进,也要在前端去解决隔离问题,其性价比很低了。

package 依赖

日常我们在使用的 npm package 的依赖,子应用是可以作为主应用的依赖来引入,构建并且发布。

这种方式最大的问题是,他们的发布流程是紧密相连的,一个子应用的新版本发布,意味着主应用需要重新构建发布。这个问题是致命的,以致于这种方式的应用我们都不会将其称为微前端架构。

这里提出是为了引入另外一个看法,就是这个 package 依赖如果不是在构建时处理,而直接是线上 script 的方式引入呢?

对,script 动态引入最新版本的依赖,解决了发布流程的问题,但实施起来还挺繁琐,你需要手动搭建好各个应用的构建,另外和服务端组合类似的,隔离性依旧是个问题。我们后边可以看到改良版的方案,即 Module Federation。

iframe

一定程度上,iframe 是浏览器自带的实现微前端非常好的方案,整合简单,隔离彻底,开箱即用。

当然它也存在一些问题:隔离太过于彻底,应用的上下文无法共享,一些场景下你需要去做同步处理,如 URL,Cookies 等。DOM 结构也是没法同步和共享,iframe 里边的内容没法突破它的那个框框。另外的就是性能考虑,每一个 iframe 本质就是一个新页面,创建和加载的开销较大。

个人觉得,一些情况下使用 iframe 就已经不错了,假如它的问题短期你都不需要考虑,那它的便利性就远远胜过了其他解决方案。

qiankun

qiankun 是蚂蚁金服出品的一个基于 single-spa 的微前端实现库。

它在这里是一个代表,即通过 JS 在运行时控制的方式来实现微前端架构需要的子应用整合和控制,子应用隔离,子应用间通信等能力。

类似的实现还有 Piralmicro-appwujie 等。

这些解决方案的优势比较明显,它们都较为综合地解决了上述提到的不同方案带来的问题,并且提供了比较不错的开发者体验,问题则是其实现有一定的复杂度,可能实施过程中会遇见的问题和具体的实现原理相关,解决起来相对困难

关于其实现,涉及的内容会比较多,后边再进行展开详细说明,

Module Federation

Module Federation 有点特殊,它是基于构建工具出来的一种解决方案,如官方所说:

Make it easier to share code between javascript applications and make team collaboration more efficient.

Module Federation

你还记得前边提到的使用 script 来动态引入子应用吗?Module Federation 可以说是这种方式的超级升级版,其通过构建工具提供的模块分析,让开发者只需要添加相应的配置来声明项目和模块的关系就可以实现项目的拆分和模块的共享

他可以用于实施微服务架构,例如我之前试验的 Demo:Tractor Store,不仅限于此,它也可以用于其他项目结构的模块共享。

Module Federation 解决的是微服务架构中模块共享和加载的问题(尤其是性能相关),但是它并没有提供隔离的解决方案。需要的时候,其实可以利用其优秀的模块共享能力,结合其他隔离的方案来实现更加优秀的微服务架构。


最后,再挖一些坑让自己慢慢埋。

关于上述提到的微前端技术实现上,还有一些细节可以深入探讨,例如如何实现子应用的代码加载如何实现隔离Module Federation 的实现原理是怎么样的,考虑到文章篇幅,这些问题放到后边我再更新更多的文章来展开讲讲。

参考内容: