微前端

微前端

微前端 是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用由单一的单体应用转变为多个小型前端应用(更简单、独立功能)聚合为一的应用,各个前端应用可以独立开发、测试、部署和运行,在共享组件的同时进行并行开发。

微前端的概念由ThoughtWorks提出的,利用微件拆分来达到工程拆分治理的方案,可以解决工程膨胀、开发维护困难等。

 

传统Web应用研发模式

  1. 将平台内多个系统放置同一个代码仓库维护 ,采用 SPA(Single-page Application) 单页应用模式

    • 优点:天生具备体验上的优势,应用直接无刷新切换,能极大的保证多产品之间流程操作串联时的流程性。

    • 缺点: 在于各应用技术栈之间是强耦合的。

  2. 将系统分为多个仓库维护,在首页聚合所有平台的入口,采用 MPA(Multi-page Application)多页应用模式

    • 优点:在于部署简单、各应用之间硬隔离,天生具备技术栈无关、独立开发、独立部署的特性。

    • 缺点: 应用之间切换会造成浏览器重刷,由于产品域名之间相互跳转,流程体验上会存在断点,卡顿、闪烁问题。

 

微前端架构应用场景

  1. 兼容遗留系统,需使用新框架去开发新功能,没必要花费精力去重构旧系统;

  2. 局部/增量升级,项目结构难以管控,开发、构建、部署变得越来越慢,开发体验持续下降;

  3. 区别交付,即以功能插件为单位,给不同的客户交付不同的插件,满足一次开发多端交付;

  4. 应用聚合,财务、考勤和项目系统分散且管理成本高,基于vue、react、JQuery的系统,将多种类型的系统聚合为一个系统;

  5. 团队间共享,跨团队开发,采用组件或服务的方式进行团队间的技术共享。其低内聚高耦合的共享,使得高质量的共享成为可能;

  6. 技术驱动,使用新技术开发新功能。

 

微前端架构的优点

  1. 技术栈无关,可以与时俱进,不断引入新技术/新框架

    前端技术栈日新月异,推陈出新的速度绝对是冠绝群雄;如何在维护好遗留系统的前提下,不断引入新技术和新框架,提高开发效率、质量、用户体验,成为每个团队需要认真对待的问题。微前端可以很好的实现应用和服务的隔离,互相之间几乎没有影响,可以很好的支持团队引入新技术和新框架, 主框架不限制接入应用的技术栈,子应用具备完全自主权。

  1. 独立开发、测试和部署

    就像微服务一样,微前端的一大优势就是可独立部署的能力。每个子应用各自管理自己的开发,测试和部署,几乎不用考虑其他代码库或管道的状态;就算旧的单体架构采用了固定、手动的发布周期,或者隔壁的团队在他们的主分支里塞进了一个半成品或失败的功能,也不影响我们的工作。如果某个微前端已准备好投入生产,那么它就能顺利变为产品,且这一过程完全由开发和维护它的团队主导、子应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新。

  2. 单一职责、独立运行时

    状态隔离,独立运行时,每个子应用之间状态隔离,运行时状态不共享。

  1. 用户体验好

    应用之间切换流畅,高内聚的系统,不需要频繁的切换系统去处理业务。

 

微前端架构的缺点

  1. 重复依赖

不同应用之间依赖的包存在很多重复,由于各应用独立开发、编译和发布,难免会存在重复依赖的情况。导致不同应用之间需要重复下载依赖,额外增加了流量和服务端压力。

  1. 复杂度高

拆分的粒度越小,便意味着架构变得复杂、维护成本变高,技术栈一旦多样化,便意味着技术栈混乱。

 

常见微前端解决方案

  1. 前端容器化,借助Iframe

  2. 应用组件化,Web Components模式

  3. 基座模式,主要基于路由分发,single-spa和qiankun就是基于这种模式

  4. EMP模式,主要基于Webpack5 Module Federation

  5. 组合式集成,即单独构建组件,按需加载,类似npm包的形式

1、 Iframe

众所周知,iframe 是 html 提供的内联框架元素,它能够将另一个 HTML 页面嵌入到当前页面中,并且能兼容所有浏览器。因此在微前端概念被提出后,iframe 成为最早的微前端解决方案,你可以用它来加载任何你想要加载的 web 应用。iframe 最大的特性就是提供了浏览器原生的 硬隔离 方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。

iframe 与微前端概念中提出的独立开发、独立维护、相互隔离非常的吻合,但 iframe 真的是最佳微前端解决方案吗?事实并非如此。《Why Not Iframe》文中提到,iframe 最大的问题也在于他的 隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。

缺点:

  1. URL 不同步,浏览器刷新 Iframe URL状态丢失、后退前进按钮无法使用(缓存解决)。

  2. UI不共享,DOM结构不共享,屏幕3/4的iframe带遮罩层的对话框,如果让它基于整个页面自适应垂直水平居中(无法解决)。

  3. 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登录效果。还有搜索引擎无法获取到其中的内容,无法实现应用的 seo等(几乎无法解决)。

  4. 慢,每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

iframe 实现的微前端解决方案很难满足现代化业务开发场景。

 

2、Web Components

Web Components 是由 google 推出的原生组件,MDN 对其定义是这样的:

作为开发者,我们都知道尽可能多的重用代码是一个好主意。这对于自定义标记结构来说通常不是那么容易 — 想想复杂的 HTML(以及相关的样式和脚本),有时您不得不写代码来呈现自定义 UI 控件,并且如果您不小心的话,多次使用它们会使您的页面变得一团糟。

Web Components 旨在解决这些问题 — 它由三项主要技术组成,它们可以一起使用来创建封装功能的定制元素,可以在你喜欢的任何地方重用,不必担心代码冲突。

三项主要技术是指:

Custom elements(自定义元素) :一组 JavaScript API,允许开发者定义 custom elements 及其行为,然后可以在用户界面中按照需要使用它们。

Shadow DOM(影子DOM):一组 JavaScript API,用于将封装的“影子”DOM 树附加到元素(与主文档 DOM 分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。

HTML templates(HTML模板) : <template> 和 <slot> 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。

Web Components原理

结合微前端的概念,Web components 在某些方面做到了微前端

  • 技术栈无关:Web Components 是浏览器原生组件,那即是在任何框架中都可以使用。

  • 独立开发:使用 Web Components 开发的应用无需与其他应用间产生任何关联。

  • 应用间隔离:Shadow DOM 的特性,各个引入的微应用间可以达到相互隔离的效果。

缺点:

  • 重写现有的前端应用。我们需要使用Web Components来完成整个系统的功能。

  • 上下游生态系统不完善。缺乏相应的一些第三方控件支持。

  • 系统架构复杂。当应用被拆分为一个又一个的组件。

 

可以利用它的特性创建可重用的定制元素(自定义style、script等),有点像可定制的Iframe,新特性兼容性不好

 

3、single-spa

  1. 全异步编程,对于用户需要提供的 load,bootstrap,mount,unmount 均使用 promise 异步的形式处理,不管同步、异步都能支持

  2. 通过劫持路由,可以在每次路由变更时先判断是否需要切换应用,再交给子应用去响应路由标准化每个应用的挂载和卸载函数(监听popstate或者hashchange,自定义路由分发机制),

  3. 不耦合任何框架,只要子应用实现了对应接口即可接入系统中

  4. 导航路由+资源加载框架

  • load 方法需要知道子项目的入口文件 (应用加载,启动,挂载和卸载等逻辑)

  • 把多个应用的运行时集成起来需要项目间自行处理内存泄漏,样式污染问题

  • 没有提供父子数据通信的方式

     

    图片

 

4、qiankun

导航路由+资源加载框架 :qiankun是基于 single-spa的微前端架构实践方案,qiankun 在 single-spa 的基础上,提供了更多可适用于生产的开箱即用的功能,如:多种资源加载方式、样式隔离、沙箱机制、全局数据存储、资源预请求等,这大概是目前微前端最成熟的实现方案【蚂蚁团队】。

  1. 路由匹配机制 :首先由主应用的路由匹配到某个子应用,框架先加载 entry 资源,待 entry 资源加载完毕,确保子应用的路由系统注册到主应用之后,再由子应用的路由系统接管 url change 事件。同时在子应用切出时,主应用应触发响应的 destroy 事件,子应用在监听到该事件后,调用自己的卸载方法卸载应用。qiankun 直接使用了社区中较为完善的 single-spa 方案。

  2. 打包形式 :qiankun 的子应用打包形式,采用的是运行时构建。在大型中后台应用开发中,独立的模块化管理显然更有价值、更值得去关注。

  3. 资源加载方式 :qiankun 提供了 JS Entry 和 HTML Entry 两种子应用资源加载方式,但通常在实际项目中我们更多的是采用 HTML Entry 加载资源。

  4. 样式隔离 :业内实现应用样式隔离的技术方案有 Shadow DOM、BEM、Dynamic Stylesheet 等,qiankun 选用动态样式表作为样式隔离解决方案,结合 HTML Entry 天生具备样式隔离的特性,能够较好地在架构层面确保应用的样式不会出现相互干扰的问题。

  5. JS 隔离 :qiankun 独创了运行时 JS 沙箱,即在应用的 bootstrap 及 mount 两个生命周期开始之前分别给全局状态打下快照,然后当应用切出/卸载时,将状态回滚至 bootstrap 开始之前的阶段,确保应用对全局状态的污染全部清零。而当应用二次进入时则再恢复至 mount 前的状态的,从而确保应用在 remount 时拥有跟第一次 mount 时一致的全局上下文。另外,沙箱还对一些全局事件监听的劫持等,以确保应用在切出之后,对全局事件的监听能得到完整的卸载,同时也会在 remount 时重新监听这些全局事件,从而模拟出与应用独立运行时一致的沙箱环境。qiankun 引入的沙箱机制,有效的避免了全局变量污染和内存泄露问题。

  6. 父子应用通信 :qiankun 实现了一套简单可用的全局数据存储,他作为 single-spa 事件的补充,父子应用均可以工读这个存储的数据。

  7. 资源预请求 :预请求充分利用了importEntry把获取资源和执行资源分离的点来提前加载所有子应用的资源。

 

5、EMP

webpack5 发布之初,其 module federation 特性就与微前端联系到一起(让代码直接在项目间利用 CDN 直接共享)。EMP 是由欢聚时代前端团队自研的单页微前端解决方案,它利用了 webpack5 module federation 新特性,实现了跨组件模块调用方式【欢聚时代团队】。

module-Federation原理学习

  • 基于 Webpack5 的新特性 Module Federation 实现,达到第三方依赖共享,减少不必要的代码引入的目的。

  • 每个微应用独立部署运行,并通过 cdn 的方式引入主程序中,因此只需要部署一次,便可以提供给任何基于 Module Federation 的应用使用。并且此部分代码是远程引入,无需参与应用的打包。

  • 动态更新微应用:EMP 是通过 cdn 加载微应用,因此每个微应用中的代码有变动时,无需重新打包发布新的整合应用便能加载到最新的微应用。

  • 去中心化,每个微应用间都可以引入其他的微应用,无中心应用的概念。

  • 跨技术栈组件式调用,提供了在主应用框架中可以调用其他框架组件的能力。

  • 按需加载,开发者可以选择只加载微应用中需要的部分,而不是强制只能将整个应用全部加载。

  • 应用间通信,每一个应用都可以进行状态共享,就像在使用 npm 模块进行开发一样便捷。

  • 生成对应技术栈模板,它能像 create-react-app 一样,也能像 create-vue-app 一样,通过指令一键搭建好开发环境,减少开发者的负担。

EMP 微前端方案除了具备微前端的能力外,它还实现了跨框架组件调用的能力

 

6、其他

 

其他

微前端发展至今,已经不再是一门具体的技术,而是整合了技术、策略和方法,可能会以脚手架、辅助插件和规范约束这种生态圈形式展示出来,是一种宏观上的架构。每一套微前端方案的设计,都是基于实际需求出发。我们要做的就是形成适合项目研发的微前端生态。

除了微前端解决方案选型之外,我们可能还需要考虑一些微前端相关的周边问题,包括:

  • 微前端周边脚手架:现在大多数开源的微前端框架都配备了脚手架工具,我们也可以选择内部定制。

  • 微前端项目配套校验库:微前端对应于解耦后,多个子项目的管理也是个不得不考虑的问题,校验库此类配套设施,应根据项目具体定制。

  • 微前端项目配套 git 工作流:微前端作为一种架构设计,会带来工作流的改变,如统一的版本发布、交付等。

  • 微前端自研构建工具(可选):构建工具受技术栈的限制,我们可选的官方方案只有 vue-cli,这是一个不错的选择,但不一定是最适合项目的选择,在 vue-cli 基础上再开发或是完全自研一套构建方案,这是值得考虑的问题。

参考资料

posted @ 2022-03-09 19:03  十盏  阅读(26)  评论(0编辑  收藏  举报