微前端框架核心技术揭秘

微前端框架核心技术揭秘

2016年由ThoughtWorks提出了一种类似微服务的概念“微前端”(Micro Frontend),其后该概念在web领域逐渐落地,在前端技术领域出现了繁多的微前端框架。本文将向你介绍有关微前端的概念、意义,带你走近微前端框架,揭秘那些“不为人知”的巧妙技术实现。

概念

什么是微前端呢?虽然它在2016年就被提出,但是直至今天,我们仍然只能描述它的轮廓,无法给它清晰下定义。以下是笔者阅读到的一些有关对微前端概念的阐述:

  • 微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用用由单一的单体应用转变为把多个小型前端应用聚合为一的应用。各个前端应用还可以独立开发、独立部署。同时,它们也可以进行并行开发。——《前端架构:从入门到微前端》
  • 微前端背后的想法是将网站或Web应用视为独立团队拥有的功能组合。 每个团队都有一个独特的业务或任务领域,做他们关注和专注的事情。团队是跨职能的,从数据库到用户界面开发端到端的功能。——译,micro-frontends.org
  • 微前端的核心价值在于 “技术栈无关”,这才是它诞生的理由,或者说这才是能说服我采用微前端方案的理由。——kuitos, qiankun作者,2020.11.20晚阿里云微前端线下沙龙
  • 真正要解决的是,当技术更新换代时,应用可兼容不同代际的应用。

微前端是一种架构,而非一个独立的技术点。我个人从两个角度去看微前端,一个是应用结构上,微前端是多个小应用聚合为一的应用形式;一个是团队意识上,微前端架构下,每个团队只负责独立(封闭)的功能,而且需要包含从服务端到客户端,团队协作意识与以往有较大不同。

微前端方案

如何在技术上落地实现微前端的概念呢?在前端技术领域出现了如下三种技术方案:

  • 基于接口协议的:子应用按照协议导出几个接口,主应用在运行过程中调用子应用导出的这几个接口
  • 基于沙箱隔离的:主应用创建一个隔离环境,让子应用基本不用考虑自己是在什么环境下运营,按照普通的开发思路进行开发即可
  • 基于模块协议的:主应用把子应用当作一个模块,和模块的使用方式无异

三种方案各有优劣,我们不能立即下结论哪一种更好。

方案类型 典型技术 优点 缺点 共同点
接口协议 single-spa 比较自由,可自主封装 无法满足很多场景
  • 子应用/模块互不干涉
  • 技术栈无关
沙箱隔离 qiankun 开发思维简单直接 沙箱带来的性能等问题
模块协议 webpack module federation 用模块思维理解引用 脱离构建工具无法使用

就目前市面上的情况而言,基于沙箱隔离的微前端方案占据了主导,也就是本文将要深入阐述的微前端框架们,也都是这类方案。其中原因,笔者认为最主要的一点,是基于沙箱隔离的方案可以让应用以最小的成本,从原本的单体大应用迁移到微前端架构上来。

微前端框架对比评测

微前端框架是用于快速让web站点或其他技术栈切换到微前端架构的底层引擎,市面上有非常多的微前端框架,笔者在2021年做过一次收集,比较有典型意义。(虽然在那之后还出现了新的微前端框架,但其大部分原理一致,因此,以下这些框架足以说明情况。)

  • Mooa:基于Angular的微前端服务框架
  • Single-Spa:最早的微前端框架,兼容多种前端技术栈。
  • Qiankun:基于Single-Spa,阿里系开源微前端框架。
  • Icestark:阿里飞冰微前端框架,兼容多种前端技术栈
  • console-os 是在阿里云控制台体系中孵化的微前端方案, 定位是面向企业级的微前端体系化解决方案。
  • Module Federation:webpack给出的微前端方案
  • Luigi:一套复杂的分布式前端应用解决方案
  • FrintJS:自主解决依赖的微前端框架
  • PuzzleJS:一套复杂的前后端编译时相结合的微前端解决方案
  • ngx-planet:基于angular的微前端框架
  • 麦饭(mfy):精巧简易的微前端框架

除了webpack的联邦模块方案需要结合构建来做,比较特殊外,其他方案都是在运行时完成应用聚合。

“子应用独立运行”指子应用不需要放到基座应用这个大环境下就能自己跑,便于调试和被不同基座引入。

“子应用嵌套子应用”是一个比较特殊的点,目前市面上能做到的框架不多。

微前端框架核心技术

在微前端架构中,存在“主应用”和“子应用”两个层级,而微前端框架的主要任务就是让子应用能够在主应用中有效运行。如上文所述,目前较多的微前端框架是基于(或支持)沙箱隔离实现的主子应用运行机制,笔者自己实现的小型微前端框架“ 麦饭”也属于此类,因此,本文只深入阐述这类微前端框架的技术原理及实现。微前端框架要解决的核心问题是 资源加载环境隔离两大问题,此外,还有路由、通信等问题。

资源加载

微前端框架需要从服务端拉取子应用的代码文件,并完成解析和子应用的挂载运行。抛开webpack的模块联邦方案,现在常见的有两种方案,分别是:以JS文件作为入口;以HTML文件作为入口。以JS文件作为入口可以直接运行JS脚本,获得JS导出的内容,但是这样,仅能加载脚本资源,无法加载CSS等样式资源。而以HTML文件为入口,则可以通过HTML文件内的文件引用,把对应的所有JS、CSS文件都一起加载,而且,web站点都是以HTML文件作为入口,这也正好可以让子应用的开发者按照web开发的思路来写子应用。

笔者在写麦饭这个框架的时候,希望直接引入子应用就能跑,所以以HTML作为入口文件。开发者使用一个特殊的importSource函数来引入入口文件,这个函数可以根据入口文件,解析子应用的全部资源,并做缓存。

解析资源

框架在获得HTML入口文件地址后,通过HTTP请求获得该文件的内容,对内容进行解析,解析时需要做资源树分析,也就是通过HTML读取所有资源文件,比如link, script[src]。在读取资源时,可能还需要读取资源本身又引入的资源。大致逻辑如下图:

在解析过程中,还需要根据registerMicroApp(麦饭提供的注册接口)的配置,决定CSS rules怎么处理。解析获得CSS的技巧,是通过