了解什么是微前端

一、简介

微前端这个术语最初来自 2016 年的 ThoughtWorks 技术雷达,说到微前端,这里不得不首先提出另一个概念“微服务”。微服务是面向服务架构(SOA)的一种变体,把应用程序设计成一系列松耦合的细粒度服务,并通过轻量级的通信协议组织起来具体地,将应用构建成一组小型服务。这些服务都能够独立部署、独立扩展,每个服务都具有稳固的模块边界,甚至允许使用不同的编程语言来编写不同服务,也可以由不同的团队来管理。微前端则是由微服务的概念扩展而来。

二、什么是微前端

以上是 Micro Frontends 网站对微前端的定义。意思是所谓微前端就是一种多个团队之间可以使用不同技术构建一个现代化 web 的技术手段以及方法策略。其中的关键字是多团队、采用不同的技术栈以及现代化的 web。微前端的思路主要继承自微服务的思想,就是让前端的多个模块或者应用解耦,做到让前端的子模块独立仓储,独立运行,独立部署。也就是如下图所示:

在这里插入图片描述

三、微前端和微服务的区别

微服务主要是业务模块按照一定的规则拆分,独立开发,独立部署,部署后通过 Nginx 做路由转发,微服务的难点是需要考虑多个模块之间如何调用的问题,以及鉴权,日志,甚至加入网关层,如下图:

在这里插入图片描述

对于微服务来说,模块分开解藕基本就完事了,但是微前端不一样,前端应用在运行时却是一个整体,需要聚合,甚至还需要交互,通信,如下图:
在这里插入图片描述

Micro Frontends的核心理念就是将网站或Web应用视为独立团队拥有的功能组合。每个团队都有一个独特的业务或任务领域,做他们关注和专注的事情。团队是跨职能的,从数据库到用户界面开发端到端的功能。

四、微前端的特点(优势)

微前端简单来讲就是将庞大的整体拆成可控的小块,并明确它们之间的依赖关系。其关键的优势在于:

1.复杂度可控,代码库更小、更内聚
比起一整块的前端代码库,微前端架构下的代码库倾向于更小/简单、更容易开发。每一个UI业务模块由独立的前端团队开发,避免代码巨无霸,保持开发时的高速编译,便于维护与开发效率。此外,更重要的是避免模块间不合理的隐式耦合造成的复杂度上升。
2.技术选型灵活
这点也是最具有吸引力的一点。技术选型是去中心化的,在同一个项目下,每个团队可以根据自身的需求以及行业的现状去自由选择如今市面上所有适合的前端技术栈,也包括未来的前端技术栈。

3.渐进的升级、更新甚至重写部分前端功能成为了可能
理想的代码自然是模块清晰、依赖明确、易于扩展、便于维护的……然而,实践中出于各式各样的原因:
•历史项目,祖传代码
•交付压力,当时求快
•就近就熟,当时求稳……

总存在一些不那么理想的代码:
•技术栈落后,甚至强行混用多种技术栈
•耦合混乱,不敢动,牵一发何止动全身
•重构不彻底,重构-烂尾,换个姿势重构-又烂尾……

要对这些代码进行彻底重构的话,最大的问题是很难有充裕的资源去大刀阔斧地一步到位,在逐步重构的同时,既要确保中间版本能够平滑过渡,同时还要持续交付新特性。所以,为了实施渐进式重构,我们需要一种增量升级的能力,先让新旧代码和谐共存,再逐步转化旧代码,直到整个重构完成。
这种增量升级的能力意味着我们能够对产品功能进行低风险的局部替换,包括升级依赖项、更替架构、UI 改版等。另一方面,也带来了技术选型上的灵活性,有助于新技术、新交互模式的实验性试错。

4.独立部署
项目中的每一个模块可单独部署,颗粒度可小到单个组件的UI独立部署,不对其他模块有任何影响。独立部署的能力在微前端体系中至关重要,能够缩小变更范围,进而降低相关风险。因此,每个微前端都应具备有自己的持续交付流水线(包括构建、测试并部署到生产环境),并且要能独立部署,不必过多考虑其它代码库和交付流水线的当前状态:

在这里插入图片描述

就算旧的系统是按固定周期季度发布或手动发布的,甚至隔壁团队误发布了一个半成品或有问题的特性也无关紧要。也就是说,如果一个微前端已经准备好发布了,它就应该随时可发布,并且只由开发维护它的团队来定。

5.团队自治
除代码库及发布周期上的解耦之外,微前端还有助于形成完全独立的团队,由不同团队各自负责一块产品功能从构思到发布的整个过程,团队能够完全拥有为客户提供价值所需的一切,从而快速高效地运转。为此,应该围绕业务功能纵向组建团队,而不是基于技术职能划分。最简单的,可以根据最终用户所能看到的内容来划分,比如将应用中的每个页面作为一个微前端,并交给一个团队全权负责。与基于技术职能或横向关注点(如样式、表单、校验等)组织的团队相比,这种方式能够提升团队工作的凝聚力。
在这里插入图片描述

6.容错
因为微前端的核心就是独立,每个业务模块由各个团队去独立负责,所以即使单个模块发生了错误,也不会影响全局。

五、何时需要微前端 (应用场景)

•项目技术栈过去老旧,相关技术的开发人员少,功能扩展吃力,重构成本高,维护成本高。
•随着系统模块的增多,项目过于庞大,单体应用变得臃肿,代码编译变慢,开发效率低下,需要一种高维度的解耦方案。
•单一技术栈无法满足新模块的业务需求。

六、实现方案

实现上,关键问题在于:
•多个Bundle如何集成?
•子应用之间怎么隔离影响?
•公共资源如何复用?
•子应用间怎样通信?
•如何测试?

1.多Bundle集成
微前端架构中一般会有个容器应用(container application)将各子应用集成起来,职责如下:
•渲染公共的页面元素,比如header,footer
•解决横切关注点(cross-cutting concerns),如身份验证和导航
•将各个微前端整合到一个页面上,并控制微前端的渲染区域和时机

集成方式分为3类:
1)服务端集成
服务端集成的关键在于如何保证各部分模板(各个微前端)能够独立发布,必要的话,甚至可以在服务端也建立一套与前端相对应的结构,每个子服务负责渲染并服务于对应的微前端,主服务向各个子服务发起请求。
2)构建时集成
常见的构建时集成方式是将子应用发布成独立的 npm 包,共同作为主应用的依赖项,构建生成一个供部署的 JS Bundle。然而,构建时集成最大的问题是会在发布阶段造成耦合,任何一个子应用有变更,都要整个重新编译,意味着对于产品局部的小改动也要发布一个新版本,因此,不推荐这种方式。
3)运行时集成
将集成时机从构建时推迟到运行时,就能避免发布阶段的耦合。常见的运行时集成方式有:
a)iframe
b)JS:比如前端路由
c)Web Components
虽然直觉上用 iframe 好像不太好(性能、通信成本等),但在这里确实是个合理选项,因为 iframe 无疑是最简单的方式,还天然支持样式隔离以及全局变量隔离。
但这种原生的隔离性,意味着很难把应用的各个部分联系到一起,路由控制、历史栈管理、深度链接(deep-linking)、响应式布局等都变得异常复杂,因而限制了 iframe 方案的灵活性。
另一种最常见的方式是前端路由,每个子应用暴露出渲染函数,主应用在启动时加载各个子应用的独立 Bundle,之后根据路由规则渲染相应的子应用。目前看来,是最灵活的方式。
还有一种类似的方式是Web Components,将每个子应用封装成自定义 HTML 元素(而不是前端路由方案中的渲染函数),以获得Shadow DOM带来的样式隔离等好处。

2.影响隔离
子应用之间,以及子应用与主应用间的样式、作用域隔离是必须要考虑的问题,常见解决方案如下:
•样式隔离:开发规范(如BEM)、CSS 预处理(如SASS)、模块定义(如CSS Module)、用 JS 来写(CSS-in-JS)、以及shadow DOM特性
•作用域隔离:各种模块定义(如ES Module、AMD、Common Module、UMD)

3.资源复用
资源复用对于 UI 一致性和代码复用有重要意义,但并非所有的可复用资源(如组件)都必须在一开始就提出来复用,建议的做法是前期允许一定程度的冗余,各个 Bundle 在各自的代码库中创建组件,直到形成相对明确的组件 API 时再建立可供复用的公共组件。

另一方面,资源分为以下 3 类:
•基础资源:完全不含逻辑功能的图标、标签、按钮等
•UI 组件:含有一定 UI 逻辑的搜索框(如自动完成)、表格(如排序、筛选、分页)等
•业务组件:含有业务逻辑
其中,不建议跨子应用复用业务组件,因为会造成高度耦合,增加变更成本。

对于公共资源的归属和管理,一般有两种模式:
•公共资源归属于所有人,即没有明确归属
•公共资源归集中管理,由专人负责
从相关经验来看,前者很容易衍变成没有明确规范,且背离技术愿景的大杂烩,而后者会造成资源创建和使用的脱节,比较推荐的模式是开源软件的管理模式:即,所有人都能补充公共资源,但要有人(或一个团队)负责监管,以保证质量、一致性以及正确性。

4.应用间通信
其常用的方式有以下三种:
1)通过路由传参的方式也可以作为一种通信手段,可以达到页面级共享,能够全局访问。
2)浏览器的原生 API,Custom Event 自定义事件可以与其他任何技术和框架一起工作。比如,我们可以将消息从Vue组件发送到 React 组件。通过自定义事件间接通信是一种避免直接耦合的常用方式。

但原则上,无论采用哪种方式,都应该尽可能减少子应用间的通信,以避免大量弱依赖造成的强耦合。

5.测试
每个子应用都应该有自己的全套测试方案,特殊之处在于,除单元测试、功能测试外,还要有集成测试:
•集成测试:保证子应用间集成的正确性,比如跨子应用的交互操作
•功能测试:保证页面组装的正确性
•单元测试:保证底层业务逻辑和渲染逻辑的正确性
现在行业内微前端比较成熟的框架是“Single-spa”和蚂蚁金服的“QianKun”,而“QianKun”是基于Single-spa进行二次开发实现的,所以使用“QianKun”会更加的简单些。

七、总结

类似于微服务之于后端,前端业务在发展到一定规模之后,也需要一种用来分解复杂度的架构模式,于是出现了微服务思想在前端领域的应用,即微前端。主要目的在于:
•技术架构上进一步的扩展性(模块边界清晰、依赖明确)
•团队组织上的自治权
•开发流程上能独立开发、独立交付
最大的意义在于解锁了多技术栈并存的能力,尤其适用于渐进式重构中架构升级过渡期;允许低成本尝试新技术栈,甚至允许选用最合适的技术栈做不同的事情(类似于微服务中允许用不同的语言编写不同服务)。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值