7月阅读周·前端架构:从入门到微前端 | 微前端实战
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读六个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》。
当前阅读周书籍:《前端架构:从入门到微前端》。
微前端实战
无论是对于从头开发的微前端应用,还是正在迁移的微前端应用,这种架构的演进都需要一个实施时间。出于以下目的,我们需要快速“发布”MRV版本(最小可发布版本)的微前端架构应用:
- 架构在项目中的可行性验证。
- 向领导和团队证明架构的可能性。
- 增强团队对于新技术的信心。
路由分发式微前端
在一个单体前端、单体后端应用中,有一个典型的特征,即路由是由框架来分发的,框架将路由指定到对应的组件或者内部服务中。微服务在这个过程中做的事情是,将调用由函数调用变成了远程调用,如远程HTTP调用。微前端与之类似,它是将应用内的组件调用变成更细粒度的应用间组件调用,即原先我们只是将路由分发到应用的组件执行,现在则需要根据路由来找到对应的应用,再由应用分发到对应的组件上。
路由分发式微前端,即通过路由将不同的业务分发到不同的独立前端应用上。其通常可以通过HTTP服务器的反向代理来实现,或者通过应用框架自带的路由来解决。
就当前而言,通过路由分发式的微前端架构应该是采用最多、最易采用的“微前端”方案。但是这种方式看上去更像是多个前端应用的聚合,即我们只是将这些不同的前端应用拼凑到一起,使他们看起来像一个完整的整体,但是它们并不是一个整体,每次用户从A应用到B应用的时候,需要刷新一下页面。
遗留系统微前端:使用iframe作为容器
当我们在实现一个平台级应用时,会在系统中集成第三方系统,或者集成多个不同部门团队下的系统,显然这是一个不错的方案。典型的场景如将传统的Desktop应用迁移到Web应用。
在采用iframe的时候,我们需要做两件事:
- 设计管理应用机制。
- 设计应用通信机制。
两者都需要经过一定的设计,而当前并没有完整的解决方案:加载机制。是指在什么情况下,我们会加载、卸载这些应用。在这个过程中,采用怎样的动画过渡,让用户看起来更加自然。
通信机制。直接在每个应用中创建postMessage事件并监听,并不是一个友好的事情。其本身对于应用的侵入性太强,因此通过iframeEl.contentWindow去获取iframe元素的Window对象是一个更简化的做法。此外,我们需要定义一套通信规范:事件名采用什么格式、什么时候开始监听事件、什么时候解绑监听事件等。
微应用化
微应用化是指,在开发时应用都是以单一、微小应用的形式存在的,而在运行时则通过构建系统合并这些应用,组合成一个新的应用。
微应用化与前端微服务化架构类似,它们在开发时都是独立应用,在构建时又可以按照需求单独加载。如果以微前端的单独开发、单独部署、运行时聚合的基本思想来看,微应用化就是微前端的一种实践。只是使用微应用化意味着我们只能使用唯一的一种前端框架。如果从框架不限的角度来定义,微应用化怕是离微前端有些远,好在大部分团队不会想着同时支持多个前端框架。当然,在一些非核心业务上,可以尝试使用新框架。
除了限制开发人员使用同一个框架,它还有一些缺点:
- 所有应用的依赖需要统一。一旦依赖版本不一致,可能会带来其他问题。
- 高度依赖于持续集成。每个子应用在提交的时候,都会重新构建出整个应用。一旦一个子应用出错,系统就会出错。它的优点是:实现简单、成本较低。
前端微服务化
前端微服务化是指,在不同的框架之上设计通信、加载机制,以在一个页面内加载对应的应用。当我们谈及前端服务化时所希望的是:
- 应用可以自动加载、运行,并能够与应用注册表进行联系。
- 每个应用的开发是完全隔离的,开发时互不影响。它可以接入某个框架,以更好地支持构建。
应用配置,针对不同的项目各有不同。有的项目已知应用数量,出于拆分需要而采用配置文件。有的项目应用数量多,并且需要支持第三方应用,需要有一个服务来进行相应的配置和管理。虽然如此,它们也有一定的适用性,如:
- 应用的挂载DOM节点。
- 应用的服务地址。
- 应用的唯一标识符。
- 应用的名称。
- 应用所需要加载的脚本文件。
对于应用的隔离,则需要深入不同的框架代码中了解不同框架的生命周期,才能有针对性地写出每个框架的加载机制。好在社区已经有如Single-SPA这样的微前端架构方案,它已经有针对不同框架的应用加载示例。此外,我们需要注意的是:
- 在加载应用时的事件绑定及应用入口。
- 在卸载应用时的事件解绑。
微服务化设计方案
从相关的前端微服务化方案上来看,我们将其分为两种:
- 通用型微前端方案。即可以适配不同的前端框架,更适合于迁移型的微前端项目。
- 定制型微前端方案。即只适配一种前端框架,适合于从头开发的微前端项目。
采用通用型微前端方案或者定制型微前端方案,取决于我们是否进行深度定制?如果我们只是保证旧系统的代码可以直接运行在新的服务上,那么通过通用型方案就能解决问题。而如果我们还需要进行一系列的定制,那么就要编写适合自己的架构加载方案。而定制也意味着,需要投入额外的成本进行研发。
不论哪种方法,目前都采用基座化的方式来加载其他应用。基座化方式可以支持加载不同的前端框架,以及在基座工程上绑定业务逻辑。依这种方案来看,我们可以将基座分为两种模式:
- 瘦基座。其只包含微前端方案相关的框架代码,而核心的业务代码则是由基座加载过来的。
- 胖基座。前端方案相关的代码与业务逻辑代码包含在同一个代码库中。
两种模式从本质上看,区别主要在于业务逻辑是否绑定。
通用型前端微服务化:Single-SPA
Single-SPA自称是一个JavaScript的元框架(Meta-Framework)。它可以用于构建可共存的微前端应用,每个前端应用都可以用自己的框架编写。它能实现如下内容:
- 在同一页面上使用多个框架(React、AngularJS、Angular、Ember等),而不用刷新页面。
- 使用新的框架编写前端代码,而无须重写现有的应用程序。
- 延迟加载前端应用和代码,用于改善初始加载时间。
Single-SPA是一种瘦基座的架构模式,这种基座只负责按照生命周期规范来处理应用,并不负责应用的生命周期实现。子应用具体的生命周期是由自身来完成的,基座只负责按自己定义的规范来执行。
1、Single-SPA的一些优势:
- 能支持大部分主流的前端框架,也能支持传统的前端框架。
- 提供更好的用户体验。即不需要页面跳转,直接在当前页面载入。
- 方便于迁移旧的遗留系统。
2、Single-SPA拥有以下的缺陷:
- 系统构建复杂。应用需要集成在一起进行构建。
- 不支持不同应用的部署分离。
- 代码结构复杂。
- 有额外的大量学习成本。
定制型前端微服务化:Mooa
基于Mooa框架的基本架构模式:
- 主工程,负责加载其他应用,以及用户权限管理等核心控制功能。
- 子应用,负责不同模块的具体业务代码。
在这种模式下,由主工程来控制整个系统的行为,子应用则做出一些对应的响应。
iframe隔离
由于应用间的冲突并不好解决,因此在设计的过程中,我们可以考虑引入iframe来隔离应用。并且,我们可以提供特制的iframe模式,对于使用Mooa框架的开发者来说,只需要进行一个配置改动就可以。
要想控制不同的iframe需要做到以下几点:
- 为不同的子应用分配ID。
- 在子应用中进行hook,以通知主应用:子应用已加载。
- 在子应用中创建对应的事件监听,来响应主应用的URL变化事件。
- 在主应用中监听子程序的路由跳转等需求。
这些相关的实现机制,都由框架本身来实现。
组件化微前端:微件化
在微前端下的微件化指的是,每个业务团队编写自己的业务代码,并将编译好的代码部署(上传或者放置)到指定的服务器上。在运行时,我们只需要加载相应的业务模块即可。
尽管微件化的定义中部署的代码是已编译好的代码,但是实际上,它可以是源码,又或者是某种特定的语言。按照广义的微件化方式可以将微件化方式划分为三种:
- DSL微件化,即通过创建领域特定语言(DSL)来实施微件化。
- 预编译微件化。
- 运行时编译微件化。
对于微件化的方案来说,如果存在第三方开发组件,就不得不考虑寻找如iframe这样的隔离方案。从上面的定义我们发现,微件化并不适合于复杂的前端应用,但是它可以作为微前端方案的一种。
对于传统的多页面应用来说,微件化是相当容易实施的方案。在传统的多页面应用结构中,只需要编写相应的HTML、CSS,以及JavaScript,就可以在加载微件时创建相应的组件和元素,再替换到.相应的DOM结点上。在今天看来,这种方式更类似于WebComponents。
面向未来:Web Components
Web Components是一套技术,允许开发人员创建可重用的定制元素(功能封装在代码之外),可以在Web应用中使用它们。
Web Components无论从名称还是定义上看,都特别适合作为一个组件、微件而存在。
通过Web Components方式实现的事情都是原生的,不需要开发人员自己编写。根据是否与现有的框架结合,我们可以将Web Components的微前端方案分为两种:
- 纯Web Components方式。
- 结合Web Components的方式。
光从名称上就可以看出两者的不同之处。
总结
本文主要介绍了六种不同的方式来实现微前端架构。每一种微前端架构方案都有各自的优缺点及适应场景,在选型的时候,需要按照自己的真实需要来选择。当出现一些不可抗力(如领导、KPI)影响的时候,也应该从中选择合适的方案。
不同的微前端架构方案的对比如图:
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)