【译】采用微前端架构

采用微前端架构

原文javascript

考虑到关于微前端的第一篇文章的大量反馈,以及咱们在 DAZN 采用的方式收到的问题,我决定分享更多有关这个话题的内容。html

在这篇文章中,我将一一介绍微前端架构各类可能的实现。前端

尽管微前端是咱们前端应用的新模型,但许多公司都已经试图接受它们背后的原则,而且已经缔造了多种实现方式,来解决它们的前端和组织上的挑战。java

在开始考虑咱们如何设计咱们的实现以前,我认为值得一提的有一些方式,这不是一个详尽的列表,但有趣的是,它们能够被用来了解可用的不一样可能性:git

  • Spotify

在桌面端中使用微前端,利用 iframe 将同一视图的不一样部分拼接在一块儿。github

iframe 之间的通讯是经过事件总线进行的,该事件总线很好地分离了应用的不一样部分,容许它们在不知道谁将要收听消息或事件的状况下进行通讯。 此外,这种方法能够节省大量的时间来管理应用内存,由于每次咱们更改 iframe 位置时,全部对象均可以自动进行垃圾回收。web

Spotify 的微前端方式

  • 宜家

决定采用不一样方式实施微前端,他们使用的是 Edge Side Includes(ESI)与 Client Side Includes(CSI)混合,我不想在这个技术上赘述,由于它在Gustaf的帖子中被普遍说起,不过,它绝对是另外一种动态生成咱们页面内容,并在 CDN 级别或客户端缓存结果的机会,这取决于咱们想采起的方法。后端

  • OpenComponents

它是 Skyscanner、OpenTable 等几家公司使用的有意思的框架。浏览器

OpenComponents 是一个以自我为中心(opinionated)的框架,它利用端到端组件(前端+后端)的概念,把这些组件提交给一个寄存器,而后用来组合一个应用。缓存

还有,在这种状况下,咱们能够在 OpenComponents 项目网站上找到更多的信息。

在这 3 个实现之间,咱们能够找到类似的地方,但其中的一些差别,会被中大型规模的组织用来建立独立和技术不可知的微前端。这方面值得一提的是 Zalando 或 BuzzFeed 也是做为这个思想流派中的另外一种贡献者。

若是咱们想总结一下到目前为止讨论的实现,咱们能够列出 3 种不一样的方法:

。使用iframes + 事件总线 。使用 ESI 结合(或不结合)CSI 。使用 OpenComponents 或相似的运行时/编译时模板系统

“DAZN 采用的方式”

正如我在本文开头所提到的,还有另外一个实现要讨论:DAZN 采用的方法。

DAZN 是一种 OTT 服务,可在多个国家/地区提供实时和点播内容。咱们的应用不只能够在网络和移动设备上使用,还能够在智能电视,机顶盒和控制台上使用,这一点很是重要,由于咱们常常遇到独特的挑战,咱们须要开箱即用地来解决它们。

一般,当咱们开始一个微前端项目时,咱们应该问本身几个问题,并基于与咱们的决策面临的相关挑战的答案,例如:

  • 咱们想在同一视图中使用多个微前端吗?
  • 咱们如何在页面之间切换路由?
  • 咱们如何在微前端之间共享数据?
  • 咱们如何生成微前端?运行时仍是编译时?

让咱们尝试回答全部的这些问题,以便理解咱们采用的方法......

咱们想在同一个视图中使用多个微前端吗?

不,咱们但愿每次加载 1 个微前端,这样咱们就没有微前端之间的共享依赖关系,每一个微前端都足够小但不过小,咱们彻底控制最终的结果,它是独立的技术和良好的封装。

咱们可使用同一框架的不一样版本,而不会影响其余微框架甚至不一样的技术,从而不会对整个应用产生任何影响。

咱们遵循领域驱动设计(DDD)实践来切割咱们的子域,并使它们真正独立地映射产品团队结构,并在由产品人员+前端开发人员+后端开发人员+功能测试+测试开发组成的大型组织内建立垂直,这对于快速迭代很是有用,在大公司须要时,团队之间的速度会有所不一样。

请记住,比你想象的更频繁,咱们的应用并不是彻底地被用户使用,例如,当用户经过身份验证时,将不会加载登陆/注册微前端的全部代码和依赖项,由于咱们只加载通过验证的区域的微前端。 同时,当用户未通过身份验证时,并非 100% 肯定她将完成登陆的流程,并成功访问应用的通过身份验证的区域,请检查你的用户与你的用户交互方式的统计信息应用,若是你没有使用它们,请使用 Google Analytics,Sentry,LogRocket 等工具投入适当的时间来建立正确的可观察性。 请记住,微前端的目标是帮助实现加载仅仅是用户须要的 而不是更多

咱们如何在页面之间切换路由?如何在微前端之间共享数据?

咱们能够经过多种方式在后端,边缘或客户端实现这一点。咱们选择客户端建立一个名为 Bootstrap 的 协调器(orchestrator),它有 4 个主要目标:

  • 微前端之间的路由
  • 加载和卸载微前端(每次 1 个,从很少个)
  • 初始化检索配置的应用
  • 公开 API 层以在微前端之间共享数据

咱们如何生成微观前端?运行时或编译时间?

咱们喜欢咱们用的人工制品的结果很是可预测,咱们但愿它们像 SPA 同样高度安全,所以咱们没有采起在运行时建立任何东西的路径,但咱们比较喜欢在编译时生成微前端,把它们存储在 AWS S3 上,并经过 Cloudfront CDN 提供服务。 经过这种方式,咱们没必要担忧在咱们为应用提供服务时扩展咱们的基础架构的问题或发生不可预测的边缘状况,咱们能够在部署生产环境以前运行端到端测试和性能测试,从而在上线以前对咱们部署的内容更有信心。

架构

在咱们的案例中,咱们决定将应用拆分为多个子域,以便提早研究用户如何与咱们的 Web 应用进行交互。对于绿地(green-field)项目,我建议深刻了解你的用户如何与你的 UX 和产品团队一块儿与应用进行交互,并遵循领域驱动设计用于定义子域及其相关的边界上下文。 对于 DAZN 应用,几乎每一个子域在技术上都被转换为单页应用,但也有一些例外,例如,因为该子域的普遍范围,视频播放器是一个组件,而后这些组件被导入到微前端内部和任何其余库同样。

微前端由引导程序加载和协调,引导程序是嵌入在主 HTML 页面中的简单的 vanilla javascript 应用,它根据深层连接(deep-link)来请求加载不一样的微前端,用户状态或任意请求都来自加载的微前端。

这就是咱们的架构的样子:

引导程序在应用的生命周期中始终可用

引导程序在咱们的应用的生命周期中始终可用,它负责加载咱们的微前端,并在设备和微前端之间暴露一层微小的抽象。

当你的目标是多个设备而不只仅是浏览器时,也就是咱们在许多智能电视,机顶盒和控制台上均可以使用咱们的应用时,这个细节变得更加相关,它们一般都有不一样的要求和I/O API ,他们被顺延封装在引导程序级别。

经过这种方式,咱们能够在多个设备中运行微前端而无需更改一行代码,由于引导程序正在抽象运行微前端的平台。

若是咱们想总结应用在浏览器中的加载方式,咱们能够说:

  1. 用户在浏览器中输入咱们的域名请求咱们的 Web 应用
  2. 提供引导程序
  3. 引导程序初始化应用,并从 API 层检索一些配置
  4. 基于初始状态和用户请求(深层连接或默认 URL)加载正确的微前端
  5. 用户沉浸在咱们基于微前端的Web应用中!

请记住,每一个微前端都是独立的,所以咱们不会在微前端之间共享组件或逻辑。

若是你认为这是浪费时间和精力,你就没法想象每一个团队在这个决策中得到了多少独立性。

代码重复并不老是一种糟糕的作法,正如咱们过去所了解的那样,一般跨团队依赖和代码抽象风险比建立相同组件的 3 到 4 倍更危险和繁琐。

咱们注意到,花费适当的时间来分析用户流并识别子域能够减小重复次数。

此外,咱们注意到使用微前端的话,因为最初分析项目并建立有意义的子域,所以跨团队的依赖关系并不像其余项目那样常常发生。

若是在你的状况下,它是绝对必须重用的组件,有一种方法可使用 Web 组件来减轻重复,以标准化组件代码,使用这种技术,它能够与任何框架结合使用,但这个讨论应该在另外一篇帖子里😉。

当咱们开始迈向微前端时,对我来讲很是清楚的是必须考虑开发团队的将来,而不只仅是解决技术问题。

借助微前端,咱们可以在不影响交付速度的状况下提供我所寻求的独立性,每一个团队都拥有端到端的特定域,保证了添加新功能,修复错误或添加改进的简单方法,没有冒着对咱们的多个开发中心传播的其余应用或依赖关系产生影响的风险。

与新开发人员加入公司以及在个人会谈或在线研讨会期间屡次分享这些信息后,我知道你可能会有大量关于引导程序的问题,它如何加载微前端,如何共享数据等等。

我将在下一篇文章中回答全部这些问题,这些问题将集中在引导程序上,因此请跟随我,不要错过微前端世界中的深潜。

若是你对微型前端有任何好奇或疑问,请随时与我联系,我老是热衷于尽量多地帮助社区😁!

相关文章
相关标签/搜索