7月阅读周·前端架构:从入门到微前端 | 架构设计:微前端架构

举报
叶一一 发表于 2024/07/23 15:03:51 2024/07/23
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读六个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读六个月。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》

当前阅读周书籍《前端架构:从入门到微前端》

架构设计:微前端架构

微前端

微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用由单一的单体应用转变为把多个小型前端应用聚合为一的应用。各个前端应用还可以独立开发、独立部署。同时,它们也可以进行并行开发——这些组件可以通过NPM、Git TagGit或者Submodule来管理。

微前端架构

微前端的实现意味着对前端应用的拆分。拆分应用的目的并不只是为了在架构上好看,它还可以提升开发效率。比如10万行的代码拆解成10个项目,每个项目1万行代码,要独立维护每个项目就会容易得多。而我们只需要实现应用的自治,即实现应用的独立开发和独立部署,就可以在某种程度上实现微前端架构的目的。

为什么需要微前端

1、遗留系统迁移

解决遗留系统,才是人们采用微前端方案最重要的原因。

过去那些使用Backbone.js、Angular.js、Vue.js等框架所编写的单页面应用,已经在线上稳定地运行了,也没有新的功能。对于这样的应用来说,我们也没有理由浪费时间和精力重写旧的应用。而这些应用是使用旧的、不再使用的技术栈编写的,由于框架本身已经不更新(不增加新功能或者不再维护),因此应用可以称为遗留系统。既然应用可以使用,就不花太多的力气重写,而是直接整合到新的应用中去。

2、后端解耦,前端聚合

事实上,采用微服务架构的组织和机构,一般都是大中型规模的。在这些大型组织机构里,采用微服务的原因主要还是,使用微服务架构可以解耦服务间的依赖。

而在前端微服务化上,则恰恰与之相反,人们更想要的结果是聚合前端应用,尤其是那些To B(to Bussiness,面向企业)的应用。

3、热闹驱动开发

所谓热闹驱动开发指的是,软件开发团队所做的软件架构或技术栈的决策,其中很多决策并没有经过踏实的研究和对目标成果的认真思考,而是不准确的意见、社交媒体的信息,或者就是些“热闹”的玩意。

微服务、微前端便是这样一些“热闹”的玩意,可以预见的是,未来将有越来越多的前端应用采用这样的架构。热闹了,对于整个技术社区来说,起着一定的促进作用——变得更加热闹。但是,采用之前记得先看看别人的失败经验,再想方设法进行一些细致的调查:构建原型、测试应用、寻找合适的人等。

微前端的技术拆分方式

从技术实践上,微前端架构可以采用以下几种方式进行:

  1. 路由分发式。通过HTTP服务器的反向代理功能,将请求路由到对应的应用上。
  2. 前端微服务化。在不同的框架之上设计通信和加载机制,以在一个页面内加载对应的应用。
  3. 微应用。通过软件工程的方式,在部署构建环境中,把多个独立的应用组合成一个单体应用。
  4. 微件化。开发一个新的构建系统,将部分业务功能构建成一个独立的chunk代码,使用时只需要远程加载即可。
  5. 前端容器化。将iframe作为容器来容纳其他前端应用。
  6. 应用组件化。借助于Web Components技术,来构建跨框架的前端应用。

微前端的业务划分方式

与微服务类似,要划分不同的前端边界不是一件容易的事。就当前而言,以下几种方式是常见的划分微前端的方式:

  • 照业务拆分。
  • 按照权限拆分。
  • 按照变更的频率拆分。
  • 按照组织结构拆分。
  • 跟随后端微服务划分。

因为每个项目都有自己特殊的背景,所以切分微前端的方式就不一样。即使项目的类型相似,也存在一些细微的差异。

微前端的架构设计

构建基础设施

在基础设施上,微前端架构与单体应用架构有相当大的差异。在单体应用里,共享层往往只有一个。而在微前端架构里,共享层则往往存在多个,有的是应用间共用的共享层,有的是应用内共用的共享层。在微前端设计初期,构建基础设施要做如下几件事情:

  • 组件与模式库。在应用之间提供通用的UI组件、共享的业务组件,以及相应的通用函数功能模块,如日期转换等。
  • 应用通信机制。设计应用间的通信机制,并提供相应的底层库支持。
  • 数据共享机制。对于通用的数据,采取一定的策略来缓存数据,而不是每个应用单独获取自己的数据。
  • 专用的构建系统(可选)。在某些微前端实现里,如微件化,构建系统用于构建出每个单独的应用,又可以构建出最后的整个应用。

提取组件与模式库

系统内有多个应用采用同一框架的微前端架构,模式库作为微前端架构的核心基础,可以用于共享代码。通过之前的组件库、设计与系统相关的实践,我们已经有了一个基础的共享模式库。在这个库里,它会包含我们所需要的基础组件,可以在多个前端应用中使用。同时,结合第4章的相关内容为组件库创建版本机制,设计相应的发布周期,以支持整个系统内应用的开发。

应用通信机制

解决了应用间共享代码的问题,我们还需要设计出一个应用间通信的机制。在微前端架构里,从应用间的关系来看,存在如下两种类型的通信:

  • 同级通信,即挂载在同一个HTML Document下的应用间的通信。
  • 父子级通信,即采用iframe形式来加载其他应用。

前者往往通过全局的自定义事件(CustomEvent)便可以实现。值得一提的是,在IE浏览器上需要使用Polyfill兼容库。此外,由于应用之间共享一个Window,所以我们还可以开发自己的发布-订阅模式组件。与自定义事件相比,它拥有更高的可定制度。

数据管理

单页面应用是指对于业务状态的管理及处理。过去这部分内容往往是由后端来实现的,即由Session来维持一个用户的状态,现在这个状态转交给了前端。前端在与后端进行交互时,需要传递大量的状态,这时的状态主要由两个部分来组成:URI(GET的传递参数会转换到URI中)+请求body。由于一个应用持有这些状态,所以为了实现方便,需要在应用间共享这些数据。

应用的数据管理可以分为两部分,一部分是状态,另一部分则是应用数据。只是从某种意义上来说,状态是一种特殊的应用数据,它更加显式地展示数据。通过上部分的应用通信机制,可以解决部分数据共享问题,通用部分的数据,则可以选择一个合适的数据管理策略。为此,我们需要一个去中心化的管理数据,或者基于基座应用的数据管理机制。

专用的构建系统

首先需要声明一下,并非所有的微前端架构都需要一个专用的构建系统。只有那些依赖于构建及构建工具创建出来的微前端应用,才需要设计出一个专用的构建系统,以支撑系统的开发。

如果我们采用了微应用化、微件化的架构方案,就需要设计自己的构建流程、构建系统,每种方式在具体实现上各有差异。微件化需要修改构建工具,如添加对应的构建插件,使它能支持构建出组件包;微应用化则依赖于设计构建流程,而不需要对构建工具进行修改。

微前端的架构模式

从微前端应用间的关系来看分为两种:基座模式(管理式)、自组织式,分别对应两种不同的架构模式:

  • 基座模式。通过一个主应用来管理其他应用。设计难度小、方便实践,但是通用度低。
  • 自组织模式。应用之间是平等的,不存在相互管理的模式。设计难度大,不方便实施,但是通用度高。

就当前而言,基座模式实施起来比较方便,方案上也是蛮多的。

不论哪种方式,都需要提供一个查找应用的机制,在微前端中称为服务的注册表模式。和微服务架构相似,不论哪种微前端方式,都需要有一个应用注册表的服务,它可以是一个固定值的配置文件,如JSON文件,或者是一个可动态更新的配置,又或者是一种动态的服务。它主要做以下一些事情:

  • 应用发现。让主应用可以寻找到其他应用。
  • 应用注册。即提供新的微前端应用,向应用注册表注册的功能。
  • 第三方应用注册。即让第三方应用接入系统中。
  • 访问权限等相关配置。

应用在部署的时候,可以在注册表服务中注册。如果基于注册表来管理应用,那么使用基座模式来开发就比较方便。

微前端的设计理念

中心化:应用注册表

微服务从本质上说应该是去中心化的。但是,它又不能完全去中心化。因为对于一个微服务来说,它需要一个服务注册中心:服务提供方要注册通告服务地址,服务的调用方要能发现目标服务。

对于一个前端应用来说,我们也需要拥有一个应用注册表,它将拥有每个应用及对应的入口。在前端领域里,入口的直接表现形式可以是路由,或是对应的应用映射。应用在构建完成,或者部署到服务器后,应该在这个应用注册表中注册,才能及时地向其他应用提供访问的权限。

标识化应用

标识化应用是指,建立某种规则来区分不同的应用,类似于唯一标识符,即ID。我们需要这个ID来标识不同的应用,以便在安装和卸载的时候,能寻找到指定的应用。

在同一个组织下,不可能有两个项目的名称是一样的。既然如此,那么就由开发系统的人为开发应用的人分配一个ID就可以了。

对于第三方应用来说,我们往往会给它们添加对应的前缀,如3rd-xxx,以区分不同的应用。并且第三方应用需要向系统申请,才能接入这个系统中。

生命周期

前端微架构与后端微架构的最大不同之处,也在于此——生命周期。微前端应用作为一个客户端应用拥有自己的生命周期,生命周期包括如下3个部分:

  1. 加载应用。
  2. 运行应用。
  3. 卸载应用。

高内聚,低耦合

在设计各个子应用及主应用的过程中,需要遵循高内聚、低耦合的原则。

高内聚,即模块内的关系,一个软件模块只由相关性很强的代码组成。设计的过程就是识别、度量模块内的联系,再将相关的行为聚集在一起,把不相关的行为放在别处。如果想要修改模块中某一部分的行为,只需要修改一处代码即可,而不需要修改多处。在实践的过程中,主要基于单一职责和关注点分离两个原则来实现。

低耦合,即模块间的关系。对于微架构系统来说,在服务之间、应用之间如果实现了松耦合,那么修改一个服务和应用就不需要修改另一个服务和应用。除了基座应用,每个应用都不应该关心协作应用的相关信息。

总结

本篇文章的核心内容如下:

  • 需要微前端的原因:遗留系统迁移、聚合前端应用及热闹驱动开发。
  • 单体前端应用拆分成微前端架构的几种方式:路由分发式、前端微服务化、微应用、微件化、前端容器化、应用Web Components化。不同的方式都有各自的适用场景。而技术和业务的关系决定了我们在拆分的时候往往需要从业务的角度来考虑技术问题。
  • 从业务的角度来拆分前端应用:按照业务拆分、按照权限拆分、 按照变更的频率拆分、按照组织结构拆分、跟随后端微服务进行划分。
  • 了微前端设计的知识——基础设施构建、架构模式及设计理念,它将有助于我们设计出更好的微前端架构应用。



作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。