一文读懂微前端技术与设计方案

122 阅读6分钟

微前端简介

2016年ThoughtWorks提出:将微服务的概念扩展到了前端世界。

在微服务框架中,后台服务已经按照业务进行了分离,但是前端还是一个单体(一个单页应用SPA,一个巨石应用),然后通过网关来调用不同的后台服务。也即是说后台服务按照业务划分,但前端还是一个整体。

微前端可以有效的改善这个问题。

其核心是运行加载多个远程应用程序。对用户而言,他加载的是一个微前端容器(Container),容器加载运行在远程服务器上的应用,然后将其作为组件、模块或者包在本地浏览器中加载并渲染[1]

2. 微前端方案

2.1 iframe 方案

该方案不建议使用。存在以下几个问题:

  1. URL不同步。主应用刷新时,iframe中 URL 状态消失,不能回退前进或前进;
  2. DOM结构不共享;变量不共享,通信困难;
  3. 加载较慢;局部弹框遮罩层问题;体验度一般;

若体验度要求不高,或者iframe中应用单一,可以考虑使用。

2.2 Nginx 方案

该方案使用较普遍。主要是利用Nginx路由代理不同后端服务。

优点有:

  1. 实现简单;不同应用可以由不同团队开发,各个团队不限框架;

缺点是:

  1. 体验度中等;切换应用时,应用加载有快有慢,白屏时间偏长,有视觉割裂感;
  2. 各个应用中存在较多重复代码或重复组件,需要团队提供统一组件包、工具库等降低重复率;
  3. 基础功能升级困难,需要每个应用各自升级;

2.3 Webpack5 Module Federation

该方案很新颖。它基于webpack5构建,允许JS应用程序加载另一个JS应用程序,而且还可以共享依赖。较成熟的框架有 EMP[2]

优点有:

  1. 去中心化;一个应用即可引用另一个应用,也可被其他应用所引用[3]

缺点是:

  1. 依赖webpack 5;
  2. 资料很少,可利用资源较少;
  3. 无法覆盖所有前端框架(EMP目前只支持Vue、React项目)

2.4 Single SPA

该方案使用很广。有一个中心化的基座容器;所有应用都注册到基座上,通过基座来监听路由,并通过路由规则来加载不同的应用。

优点有:

  1. 同一个页面上使用多个框架而无需刷新页面;
  2. 提供一个 layout 引擎,可以帮助你快速的构建微前端;

缺点是:

  1. 通信困难;
  2. 开发成本较高;

国内 Qiankun、icestark 基于该框架进行了二次封装。两者对比:

  1. 使用情况:前者在蚂蚁内部广泛使用;后者在阿里内部大量使用;
  2. 文档情况:都提供了在线文档,文档完整均不太高;但前者提供论坛;
  3. 生态情况:两者周边生态没有,依赖核心团队更新维护,但前者有umi特色;

2.5 其他方案

还有部分其他设计思路,如:利用Web Components技术来构建跨框架的前端应用。但尚无较成熟框架,从0开始难度大,存在兼容问题。

3 微前端利弊

使用微前端,有这些收益[5]

  1. 组织灵活、团队自治:不同应用根据各自团队实际情况选择适合的框架,子应用主体功能由相关团队开发、维护;
  2. 扩展性好:主应用可以根据自身需求增加或删减子应用;可快速集成应用服务;
  3. 复用性高:单个应用可以在多个不同主应用中进行复用。

同样,使用微前端,也会带来一些问题[5]

  1. 生态小:目前可用框架很少,对框架提供者依赖度高;
  2. 开发难度高:功能开发,依赖于框架提供的能力;父子应用之间的控制复杂;
  3. 协调困难:多个子应用之间功能协作困难;
  4. 版本控制困难:不同子应用之间存在版本依赖关系,维护成本高;
  5. 问题跟踪有难度:跨多个子应用时,问题跟踪调试困难,问题定位有难度;

4. 如何设计微前端架构

在设计使用微前端之前,先要考虑以下问题:

  1. 项目是否是大型复杂应用?小型应用不建议使用微前端,反而将应用变得更加负责。
  2. 项目应用是否多次被使用,需要在不同应用中被复用?应用之间相互独立,公用应用很少,使用微前端并非必要;
  3. 不同项目需要组合在一起才能提供完整功能?例如,有老旧项目需要集成到新项目中,但又不想去改造老旧项目。

如果没有上述诉求,不建议上微前端。若有需求,请继续阅读下文(下本设计方案,基于中心化架构(Single SPA)进行方案阐述,这个是纯前端的微前端)。

4.1 设计前准备

在考虑使用微前端框架来解决上述几个问题前,建议按照遵循几个要求,来较好的完成微前端实践方案的建设:

  1. 合理规划你的应用,避免应用的过多拆分,避免碎片化;
  2. 尽量减少不同应用的依赖关系;越独立越好;
  3. 定义好一些约束条件等;

4.2 架构需要实现的功能

要实现一个功能较为完备的微前端框架,需要完成以下工作[4]

  1. 建立基础组件和模板库,包括一些必要的业务组件,共享库等;
  2. 建立应用之间的通信机制:子级应用之间的通信;父子应用之间的通信;
  3. 建立数据管理机制:路由参数管理、storage数据存储管理等;
  4. 系统构建机制:父子应用之间的构建流程;
  5. 应用注册机制:包括应用注册、应用发现;
  6. 访问权限控制:包括用户登录、鉴权、导航管理等;

4.3 需要注意的问题

在开发过程中,可能遇到的问题[6]

  1. 样式污染:
    1. 可使用沙箱设计方案,尽量避免相互影响,但又会出现"Isolated Styles"问题;
    2. 或者使用 HTML Entry 方式注册子应用,该方式会牺牲性能;
    3. 或者各个应用使用各自特殊的样式前缀(第三方UI库,不好处理)
  2. 全局变量干扰:可使用沙箱设计方案,尽量避免相互影响,参考 Qiankun、icestark 实现方式;
  3. 版本管理;

4.4 一点担忧

功能好实现,但架构可能会变得不好,主要有以下几点[4]

  1. 架构设计跟不上不断变化的需求,心有余而力不足;
  2. 架构设计不合理;推倒重来不现实;
  3. 架构设计合理,后继者未能领会初创者意图构想,修修补补状况频出;
  4. 架构设计合理,但开发过程中,由于一些原因,越走越歪,背离初心;

参考资料:

[1] 一文读懂微前端架构;

[2] qiankun 和 emp 在国内微前端中为啥这么受欢迎?;

[3] Module Federation原理剖析;

[4] 架构设计:微前端架构;

[5] Microfrontends: the good, the bad, and the ugly;

[6] 可能是你见过最完善的微前端解决方案;