一.动机
在 我们 的前端开发工作中,我们往往就会遇到如下困境:
工程越来越大,打包越来越慢
团队人员多,产品功能复杂,代码冲突频繁、影响面大
内心想做 SaaS 产品,但要求总是要做定制化
不同的团队可能有不同的方法去解决这些问题。在前端开发日新月异、前端工程化蓬勃发展的今天,就衍生了另一种尝试——微前端。
二.背景
微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用可以独立运行、独立开发、独立部署。
微前端的概念由ThoughtWorks于2016年提出,此后很快被业界所接受,并在各互联网大厂中得到推广和应用。
微服务与微前端有很多相似之处,都是希望将某个单一的单体应用,转化为多个可以独立运行、独立开发、独立部署、独立维护的服务或者应用的聚合,从而满足业务快速变化及分布式多团队并行开发的需求。微服务与微前端不仅仅是技术架构的变化,还包含了组织方式、沟通方式的变化。微服务与微前端原理和软件工程,面向对象设计中的原理同样相通,都是遵循单一职责(Single Responsibility)、关注分离(Separation of Concerns)、模块化(Modularity)与分而治之(Divide & Conquer)等基本的原则。
简单地说,就是将一个巨无霸(Monolith)的前端工程拆分成一个一个的小工程。别小看这些小工程,它们也是“麻雀虽小,五脏俱全”,完全具备独立的开发、运行能力。整个系统就将由这些小工程协同合作,实现所有页面的展示与交互。
可以跟微服务这么对比着去理解:
欣赏下(阿里云)微前端的基本工作原理三. 微前端的优缺点
优点
敏捷性 - 独立开发和更快的部署周期:
开发团队可以选择自己的技术并及时更新技术栈。
一旦完成其中一项就可以部署,而不必等待所有事情完毕。
降低错误和回归问题的风险,相互之间的依赖性急剧下降。
更简单快捷的测试,每一个小的变化不必再触碰整个应用程序。
更快交付客户价值,有助于持续集成、持续部署以及持续交付。
维护和 bugfix 非常简单,每个团队都熟悉所维护特定的区域。
缺点
开发与部署环境分离
本地需要一个更为复杂的开发环境。
每个 App 模块有一个孤立的部署周期。
最终应用程序需要在同一个孤立的环境中运行。
复杂的集成
需要考虑隔离 JS,避免 CSS 冲突,并考虑按需加载资源
处理数据获取并考虑用户的初始化加载状态
如何有效测试,微前端模块之间的 Contract Testing?
第三方模块重叠
依赖冗余增加了管理的复杂性
在团队之间共享公共资源的机制
影响最终用户的体验
初始 Loading 时间可能会增加
HTML 会需要服务器端的渲染
四. 微前端应用场景
1.遗留系统的兼容与迁移:
技术的发展日新月异。采用更好更优秀的技术支持业务是很多公司提高竞争力的手段。大多数拥有已上线运营的软业系统的商业公司的开发团队面临的一个实际问题是:如何在兼容现有系统的情况下采用更新更优秀的技术与框架开发新的功能。使用微前端是一个不错的选择。
2.应用聚合
大多数公司内部都部署了各种软件应用提供各种内部与外部服务。如果能将这些软件应用聚合成一个可以提供统一用戶体验的应用将会提高员工的工作效率及客户的体验。采用微前端是一个不错的选择。
3.单一职责与应用自治
由于每个微前端应用都是独立的开发与部署并且各应用之间通过统一的接口规范与框架聚合在一起。这既可提高开发团队的专注水平又保证各团队之间的协作。
五. 微前端实现的几种方式
路由分发式。通过 HTTP 服务器的反向代理功能,来将请求路由到对应的应用上。
前端微服务化。在不同的框架之上设计通讯、加载机制,以在一个页面内加载对应的应用。
微应用。通过软件工程的方式,在部署构建环境中,组合多个独立应用成一个单体应用。
微件化。开发一个新的构建系统,将部分业务功能构建成一个独立的 chunk 代码,使用时只需要远程加载即可。
前端容器化。通过将 iFrame 作为容器,来容纳其它前端应用。
应用组件化。借助于 Web Components 技术,来构建跨框架的前端应用。
路由分发式
路由分发式微前端,即通过路由将不同的业务分发到不同的、独立前端应用上。其通常可以通过 HTTP 服务器的反向代理来实现,又或者是应用框架自带的路由来解决。
前端微服务化
前端微服务化,是微服务架构在前端的实施,每个前端应用都是完全独立(技术栈、开发、部署、构建独立)、自主运行的,最后通过模块化的方式组合出完整的前端应用。
采用这种方式意味着,一个页面上同时存在二个及以上的前端应用在运行。而路由分发式方案,则是一个页面只有唯一一个应用。
组合式集成:微应用化
微应用化,即在开发时,应用都是以单一、微小应用的形式存在,而在运行时,则通过构建系统合并这些应用,组合成一个新的应用。
微应用化更多的是以软件工程的方式,来完成前端应用的开发,因此又可以称之为组合式集成。对于一个大型的前端应用来说,采用的架构方式,往往会是通过业务作为主目录,而后在业务目录中放置相关的组件,同时拥有一些通用的共享模板
微件化
微件(widget),指的是一段可以直接嵌入在应用上运行的代码,它由开发人员预先编译好,在加载时不需要再做任何修改或者编译。而微前端下的微件化则指的是,每个业务团队编写自己的业务代码,并将编译好的代码部署(上传或者放置)到指定的服务器上,在运行时,我们只需要加载相应的业务模块即可。对应的,在更新代码的时候,我们只需要更新对应的模块即可。
前端容器化
前端容器:iframe
iframe 作为一个非常 “古老” 的,人人都觉得普通的技术,却一直很管用。它能有效地将另一个网页/单页面应用嵌入到当前页面中,两个页面间的 CSS 和 JavaScript 是相互隔离的——除去 iframe 父子通信部分的代码,它们之间的代码是完全不相互干扰的。iframe 便相当于是创建了一个全新的独立的宿主环境,类似于沙箱隔离,它意味着前端应用之间可以相互独立运行。
结合 Web Components 构建
Web Components 是一套不同的技术,允许开发者创建可重用的定制元素(它们的功能封装在代码之外),并且在 web 应用中使用它们。
目前困扰 Web Components 技术推广的主要因素,在于浏览器的支持程度。在 Chrome 和 Opera 浏览器上,对于 Web Components 支持良好,而对于 Safari、IE、Firefox 浏览器的支持程度,并没有那么理想。
业务拆分
与微服务类似,要划分不同的前端边界,不是一件容易的事。就当前而言,以下几种方式是常见的划分微前端的方式:
按照业务拆分。
按照权限拆分。
按照变更的频率拆分。
按照组织结构拆分。利用康威定律来进一步拆分前端应用。
跟随后端微服务划分。实践证明, DDD 与事件风暴是一种颇为有效的后端微前端拆分模式,对于前端来说,它也颇有有效——直接跟踪后端服务。每个项目都有自己特殊的背景,切分微前端的方式便不一样。即使项目的类型相似,也存在一些细微的差异。
六. 微前端方案的对比
关键点的相关解释如下:
框架限制。在后台微服务系统里,人们使用其它语言的库来开发新的服务,如用于人工智能的 Python。但是在前端,几乎不存在这种可能性。所以当我们的前端框架只有一个时,我们在采用微前端的技术时,可选范围就更大了。而遗憾的是,多数组织需要兼容遗留系统。
IE 问题。不论是在几年前,还是在今年,我们实施微前端最先考虑的就是对于 IE 的支持。在我遇到的项目上,基本上都需要支持 IE,因此在技术选型上就受限一定的限制。而在我们那些不需要支持 IE 的项目上,他们就可以使用 WebComponents 技术来构建微前端应用。
依赖独立。即各个微前端应用的依赖是要统一管理,还是要在各个应该中自己管理。统一管理可以解决重复加载依赖的问题,独立管理会带来额外的流量开销和等待时间。
那么,对于下表而言,表中的 a~j 分别表示上面的几种不同的架构考虑因素。(PS:考虑到 Web Components 几个单词的长度,暂时将它简称为 WC~~)
七. 微前端框架参考案例
基于MPA + iframe + Webpack实现的微前端架构
基于MPA + iframe + Webpack实现的微前端架构实现,采用了更新的技术栈,以及真正的模块化,组件化技术。Saas系统就是一个很典型的该方案的例子:
总结:
上图可知不同子系统之间可以各自维护,单独打包部署,最后通过node或者nginx做路由分发。我们采用公共的ui组件库和js类库来抽离公共组件,但是前提是不同组件库和技术栈强相关,如果没有历史遗留的新项目,建议采用一致的技术栈。
以上方案的缺点就是组件库只能复用而无法真正共享,并且切换路由会导致页面重新渲染刷新。父子系统通信困难,仍然需要iframe最为容器来通信。
《用微前端的方式搭建类单页应用(美团微前端方案)》:
需求分析:
方案选择:
美团采用了特定中心路由基座式的开发方案,并命名为:基于React的中心路由基座式微前端。在具体实现上,分为动态化方案、路由配置信息设计、子工程接口设计、复用方案设计和流程方案设计等
优点:
保证技术栈统一在React。
子工程之间开发互相独立,互不影响。
子工程可单独打包、单独部署上线。
子工程有能力复用基座工程的公共基建。
保持单页应用的体验,子工程之间切换不刷新。
改造成本低,对现有工程侵入度较低,业务线迁移成本也较低。
开发子工程和原有开发模式基本没有不同,开发人员学习成本较低。
总结:
微前端在外卖商家广告端的实践过程。总的来说,我们完成了以下的目标:
按照领域(业务线)拆分工程,工程的可维护性得到提高,相关领域进行了内聚,无关领域进行了解耦。
子工程提供了PC、H5、KA三端的物理复用土壤,消除了工程膨胀问题,工程大小也变得可控。
子工程打包速度从分钟级降为秒级,提高了开发体验,加快了上线的速度。
子工程开发支持热更新,开发体验不降级。
子工程能够单独开发、单独部署、单独上线,业务线间互不影响。
整体工程改造成本低,插拔式开发,无侵入式代码,在正常业务开发的同时短期内就可以完成上线。
开发者学习成本低,完整地保留了单页应用开发的开发体验,开发者可快速上手。开发流程:
蚂蚁的微前端落地实践qiankun - 一套完整的微前端解决方案
在中国传统文化中,qian天堂kun代表地球,qiankun宇宙代表地球。
qiankun(乾坤) 就是一款由蚂蚁金服推出的比较成熟的微前端框架,基于 single-spa 进行二次开发,用于将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。(见下图)
它主要采用HTML Entry模式,直接将子应用打出来 HTML作为入口,主框架可以通过 fetch html 的方式获取子应用的静态资源,同时将 HTML document 作为子节点塞到主框架的容器中。这样不仅可以极大的减少主应用的接入成本,子应用的开发方式及打包方式基本上也不需要调整,而且可以天然的解决子应用之间样式隔离的问题。
优点:
支持子应用并行
支持js沙箱环境(js隔离)
css隔离
HTML Entry,简化开发者使用
按需加载
公共依赖加载
父子应用通信机制
子应用嵌套
八. 总结
最后, 送人玫瑰,手留余香,觉得有收获的朋友可以点赞,关注一波 ,Single-Spa和Qiankun集成实践 文档资料 已上传至 React 中文社区交流群, 请关注公众号,点击菜单栏 入群学习,添加 入群小助手 后入群领取。陆续更新前端超硬核文章。
推荐阅读
(点击标题可跳转阅读)
[极客前沿]-你不知道的 React 18 新特性
[极客前沿]-写给前端的 K8s 上手指南
[极客前沿]-写给前端的Docker上手指南
[面试必问]-你不知道的 React Hooks 那些糟心事
[面试必问]-一文彻底搞懂 React 调度机制原理
[面试必问]-一文彻底搞懂 React 合成事件原理
[面试必问]-全网最简单的React Hooks源码解析
[面试必问]-一文掌握 Webpack 编译流程
[面试必问]-一文深度剖析 Axios 源码
[面试必问]-一文掌握JavaScript函数式编程重点
[面试必问]-阿里,网易,滴滴,头条等20家面试真题
[面试必问]-全网最全 React16.0-16.8 特性总结
[架构分享]- 微前端qiankun+docker+nginx自动化部署
[架构分享]-石墨文档 Websocket 百万长连接技术实践
[自我提升]-Javascript条件逻辑设计重构
[自我提升]-页面可视化工具的前世今生
[自我提升]-10分钟快速构建错误监控系统
[大前端之路]-连前端都看得懂的《Nginx 入门指南》
[软实力提升]-金三银四,如何写一份面试官心中的简历
觉得本文对你有帮助?请分享给更多人
关注「React中文社区」加星标,每天进步
点个赞??,顺便点个 在看 支持下我吧!