微前端是将Web应用由单一的单体应用转变为多个小型前端应用聚合为一的一种手段。本文从微前端的基础理论出发,与大家分享长亮科技Web 前端团队的探索与实践经验。
作者
Yang.Q 前端架构师
拥有10年前端开发和从业经验,负责前端生态建设以及低代码、微前端等前端前沿技术的探索工作。
数字时代,随着技术的不断变革,前后端分离架构的研发模式已成为主流。但爆发式增长的业务量让前端功能需求不断增多,小而美的应用不复存在。当一个普通应用演变成一个巨石应用( Frontend Monolith )后,逻辑复杂和臃肿的问题开始暴露,随之而来的是多人难以协作、功能耦合性高、页面加载速度变慢等一系列难题亟待解决。
当后端「微服务」广泛普及时,「微」的概念也影响到了前端,「微前端」应运而生。
微前端(Micro-Frontends)是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用,各个前端应用可以独立运行、独立开发、独立部署。
通过跟微服务进行对比,我们可以更清晰地理解微前端的概念:
相比于传统的前端工程,微前端架构具备以下几大优势:
大幅提升研发效能:将大工程进行拆分,显著提高打包构建速度,代码简洁、解耦、更易维护;
定制化编排产品:将微应用进行个性化编排组合,快速进行产品创新;
定向增量升级:各微前端单独部署,可定向增量升级某一微应用,而不影响其他微应用,大大节省了部署成本和降低升级风险。
基于丰富的技术实践经验,长亮科技Web前端团队在微前端领域的深入探索已有所建树。本文将重点分享在微服务框架的背景下,长亮科技自主研发和设计的微前端解决方案。
微前端技术选型之路
微前端架构的实现方式有多种技术路线,包括路由分发式、应用微服务化、微应用、微件化、前端容器化、应用组件化等,需根据具体场景选用合适的方式。在某些场景下,可能没有合适的方案,也可能同时使用多种方案。
因此在做技术选型前,首先需要对公司的产品现状进行整体梳理,结果如下:
现有前端框架:公司主流使用vue,但是一些老旧系统仍使用react、jquery等;
前端工程拆分粒度:大部分产品还是传统的大工程形态;有部分产品已进行了模块化、组件化拆分,将一个大工程拆分成了多个小工程,各工程通过发布npm插件的形式,最终被一个主工程安装聚合。
通过对公司现有产品的分析,最终我们最终确认了技术选型的要求:
能够做到跨技术栈,不局限于一种前端框架;
能够将npm插件改造成以微应用的形式进行聚合。
此外,根据我们的产品特性,微前端框架还需满足以下几点需求:
● 微应用独立开发
● 微应用独立部署
● 跨技术栈,不局限于一种前端框架
● 能够将npm插件改造成以微应用的形式进行聚合
● 可将微应用进行编排组合,输出不同的产品
● 加载器底座使用vue
结合公司的框架能力需求,我们最终选定三种微前端技术路线结合的方式:
应用微服务化:针对于无法拆分的系统和非vue系统,采取微服务化接入,进行技术验证后选择了阿里qiankun框架;
微应用化:针对vue技术栈已做模块化拆分的系统工程,采取微应用化接入,使用了webpack5提供的模块联邦;
前端容器化: 针对一些老旧的非spa单页面的系统,采取iframe接入。
微前端解决方案设计思路
从前文所述的微前端概念可知,中心加载器是微前端的核心所在,而加载器需具备三个基本能力:
路由分发;
加载微应用的静态资源;
可在加载器上任意上架下架微应用。
基于上述认知,我们对微前端解决方案的各个模块做了如下设计:
标识微应用
如何保证加载器能正确的识别到对应的微应用呢?
我们决定为每一个微应用定制一个唯一id标记,即编码appCode。
中心化路由
微服务的核心是注册中心,微前端是否也需要一个注册中心呢?如果需要,那么微前端的注册中心又是什么呢?
通常情况下,前端页面的渲染是靠路由来控制的,那我们是否可以利用前端的路由体系来设计一套微前端的注册中心呢?
基于这个思路,我们初步设计了一套加载器的工作流程:
1) 加载器底座拉取微应用配置信息
2) 将配置中的微应用注册到注册中心
3) 浏览器url变更驱动loader加载器加载对应微应用的资源
4) 加载微应用
微应用配置
依据上述加载器的工作流程图,我们整理出微应用的配置文件结构以及字段:
注册中心
依据上文提到的注册中心即是路由的思路,构建出如下路由结构(以vue-router为例):
以微应用唯一编码做为路由的name[path]。
这里需要注意的是,考虑到微应用的动态加载,加载器加载的微应用个数不做限制,如一次性将所有的微应用路由全部加载,势必会造成路由数据过于庞大,因此初始化时只注册中心路由,微应用对应的页面路由,则在第一次进入当前微应用的时候创建。此步骤放在loader加载器中实现。
Loader加载器
加载器通过监听路由切换,主动获取路由对应的微应用的静态资源,继而进行页面渲染。
加载器主要工作流程如下:
依据此流程可以编写出加载器的流程代码(以vue为例):
微应用设计
微应用的设计分为微服务化接入(qiankun)和微应用化接入。
1、微服务化-qiankun
首先在应用入口增加qiankun的生命周期
为了让微应用能被加载器顺利加载,其构建后的文件结构以及构建路径需做适配。
为了区分请求资源的归属,在每个静态资源前都加上了appCode(微应用编码),例如/app1/index.index,/app1/lib.js ,/app1/lib.css。因此在构建时候publicPath需设置成”./”相对路径。
构建后的文件夹一级目录下需包含微应用的配置文件和入口文件。
以下为qiankun应用打包后的文件结构:
config.json:微应用配置文件
Index.html:微应用入口文件
2、微应用化-模块联邦
模块联邦主要是利用wenpack5提供的ModuleFederationPlugin将组件模块化输出。
通过模块联邦导出组件,最终生成的文件结构如下:
config.json:微应用配置文件
remoteEntry.js:微应用入口文件
长亮科技微前端框架产品
综上所述方案设计整体思路,经过产品化打磨后,长亮科技Web前端团队基于公司现有前端低代码平台,自主研发和设计的微前端框架产品正式落地。
基础类库:为解决样式和编码规范统一等问题,需要一系列的基础类库,如基础组件库,样式库等;
微前端底座:提供基础的admin能力,通过门户布局组件提供扩展修改能力,底座核心包含注册中心,资源加载器;
微应用开发脚手架:提供标准工程结构的开发脚手架,开发者可专注于业务开发,不需重复调试编译构建等复杂的接入规范;
低代码平台输出标准微应用:通过低代码平台的可视化配置,快速输出标准的微应用,无缝接入微前端底座。
微前端部署场景示例
微前端的部署有两种形式,一种是将所有微应用的资源与底座加载器合并成一个文件夹,进行合并部署,只提供一个Web服务;另一种则是将底座和微应用分开部署,每个微应用都提供单独的Web服务。
合并部署
独立部署
问题与反思
在微前端框架的实施过程中,遇到的主要问题有如下几点:
页面样式混乱:因为微应用具备独立开发的特性,不同团队开发的微应用聚合到一起时,无法避免出现页面混乱、不统一等问题;
团队协同性差:伴随着团队自治程度的提升,协作困难等问题随之产生;
用户流量负担:独立构建意味着公共资源的冗余,继而增加用户的流量负担;
问题排查困难:当微应用与加载器底座的对接出现问题时,除框架构建者外,开发人员往往很难定位问题所在。
当前,因为技术发展的桎梏,有些问题确实难以短期内有效解决,但这也正是我们软件开发者们需要不断为之努力和探索的方向所在。未来,微前端不一定是未来发展趋势的收束点,但是它在未来一定会发挥重要作用。