在任何合法的前端开发团队中,提高可扩展性和敏捷性很少会成为头等大事。在处理大型、复杂的产品时,如何确保快速、频繁地交付同时包含后端和前端的功能?像后端那样将前端单体分解成许多更小的部分似乎是答案。如果执行得当,微前端可以提高团队的有效性和效率。就是这样。
微前端背后的想法是将网站或 Web 应用程序视为由独立团队拥有的功能的组合。每个团队都有自己关心和擅长的不同业务领域或任务。团队是跨职能的,从数据库到用户界面,端到端地开发其功能。
将较大的问题分解为较小的问题以提高敏捷性、可重用性和可扩展性一直是 IT 的圣杯之一,过去二十年来该领域取得的进展令人震惊。但是,使用越来越大的代码库的新限制仍在不断出现。业内最有头脑的人一直在努力应对这一挑战,试图从技术和组织的角度来解决这个问题。迄今为止,微服务架构肯定仍然最接近解决它。
在本文中,您将学习:
微服务架构和微前端如何运作;
他们最大的优势是什么;
实施微前端时必须满足哪些要求;
您可以使用哪些技术或方法;
以及这些解决方案中的每一个如何相互比较。
微服务架构和微前端——它们解决了什么以及它们如何运作
微服务架构承诺:
更容易构建和维护应用程序
提高团队生产力
使用技术的灵活性
可扩展性
解决方案是将大型系统拆分为围绕明确定义的业务能力组织的细粒度、松散耦合的服务。然后,每个服务都足够小,可以由一个开发团队开发,并且可以快速调整以适应新的业务需求并进行部署,而不会破坏系统的其他部分。
这种方法的危险在于系统将被分解成许多不相关的应用程序。尽管这对开发人员来说很好处理,但这并不是用户对系统的期望;大多数人不喜欢使用大量的小型应用程序来完成他们的工作。因此,必须将为此过程分解的内容重新组合到用户界面中。
将碎片重新组合在一起
常见的方法是在用户和微服务之间构建一个单一的前端层。对于每一个重要的系统,庞大的前端代码库都会威胁到微服务架构的好处。这就是微前端的用武之地。
微前端的基本思想非常简单——将用户界面由多个围绕明确定义的业务能力组织起来的细粒度部分组成。然后每个部分都足够小,可以由一个垂直结构的团队开发和拥有。拥有前端和后端的团队建立了一个真正自给自足的功能团队。
然而不幸的是,微前端带来了同样的挑战,使得微服务难以实现。此外,任何捷径都可能以负面的方式影响用户体验。必须确保一致性、安全性、互操作性、性能、可扩展性和所有权,以确保无缝的用户界面。
尽管不同的微前端方法解决了各种问题,但还没有一个能够涵盖所有这些问题。但在我们深入研究这些不同方法的细节之前,让我们先仔细看看选择微前端的主要动机,以及与单体方法相比的优缺点。
解释微前端的 3 大优势
微前端的优势#1:可扩展的团队设置
3 种不同的前端方法及其对团队组织的影响
选择微前端方法有很多很好的理由,但最重要的(如果不是最重要的)之一来自可扩展的团队设置。
至少可以确定影响开发团队组织的三种可能的前端架构:单片前端和后端、带有后端微服务的单片前端和微前端。下面,我们将描述每个团队组织的后果。
单片前端和后端
构建需要前端和后端的解决方案的常用方法是水平拆分项目并通过 REST API 在这些层之间进行通信。
如果系统足够小,可以供一个团队开发,最好的选择是保持架构简单。您可以通过创建单页应用程序 (SPA) 前端并通过 REST API 将其连接到后端来实现此目的。然后根据每一层所需的工作量调整您的团队设置。
良好的做法是确保从一开始您的代码就结构良好,并且当您的解决方案增长时,您可以引入另一个或两个团队,而无需重新构建它。
但是这种架构的局限性是显而易见的:团队修改代码库的次数越多,就需要更多的协调和集成,这会导致产品开发瘫痪。
带有后端微服务的单片前端
尤其是在大型企业中,对额外开发团队的需求通常从后端开始。大多数系统需要大量的业务逻辑。例如,它们需要在浏览器端无法完成的处理,或者与遗留系统的复杂集成。在这些情况下,一个跨职能团队已经不够了。
大多数公司扩展其架构的第一步是垂直拆分后端代码库以解决复杂性。前端被分配给一个专门的前端团队,而其余的工作则分配给各个后端团队。因此,积压的项目被分解成块,并由不同的团队交付。然后,这些团队要么通过合同谈判解决依赖关系,要么——以更敏捷的方法——通过大量积压计划来解决依赖关系。
这种方法带来的最大挑战是管理这些依赖关系和同步发布。测试也变得很麻烦,因为您需要等待所有单独的部分到达测试环境才能验证它。
当解决方案必须嵌入来自不同产品 backlog 的功能时,它变得更加复杂(这种情况经常发生)。
在更大的范围内,这种方法需要大量的管理。日常部署几乎是不可能的。这就是为什么在具有复杂前端的大型企业中工作的开发人员和架构师寻求最终垂直扩展的解决方案,将前端添加到他们已经改变游戏规则的微服务架构 - 微前端。
微前端
为了快速开发、测试和发布其功能,团队需要能够在不依赖其他团队的情况下工作。微前端可以在用户界面领域实现后端微服务的相同承诺,并且可以应用支持独立团队合作的相同原则。
在此设置中,前端和后端这两个领域紧密耦合,因为需求来自一个产品待办列表。再一次,一个团队可以在一个简单的架构中交付整个功能。如果执行得当,这不会影响用户体验。
为了很好地执行它,微前端带来了许多后端微服务已知的类似问题,必须解决。否则,用户可能仍将系统感知或体验为不同特征的拼凑。
微前端的优势#2:技术选择自由
除了创建可扩展且独立的团队设置外,微前端方法还有助于处理应用于前端的大量技术。每个季度都有关于如何开发面向用户的系统部分的新想法。很多时候,新版本的框架甚至不向后兼容,这意味着每个版本实际上都是一个单独的框架。
微服务架构的优势之一是可以自由选择所使用的技术。当用户界面被拆分成独立的模块时,前端开发人员可以享有同样的自由——至少在一定程度上。
微前端的优势#3:弹性
任何系统的实际成本都不能很好地体现在代码库的初始开发成本上,而是体现在维护上。代码重构和系统重构的无休止螺旋的目的是保持与开始时相同的速度引入功能更改。
微前端架构通过引入以下约束使代码库更具弹性:
隔离变更的影响;
防止代码耦合;
并随着时间的推移保留架构。
这些约束防止不受控制的依赖关系、限制代码重用和强制服务边界。
不再有不受控制的依赖
多年来开发的大型应用程序不可避免地充满了难以跟踪和维护的代码依赖关系。开发人员在上市时间的压力下工作,或者只是试图优化他们的工作方式,会在代码的不同部分之间产生许多不受控制的依赖关系。当引入新的依赖项时,重用一些业务逻辑、缓存数据或资源池似乎总是一个好主意。后来发生的事情是这种共享功能变化的不可预见的后果。
通过将代码库分成几个不相连的部分,很容易避免这种依赖关系。由于两者之间的自然边界,一个微前端不可能重用其他微前端的现有功能。因此,更改的任何意外副作用仅限于一个微前端。
有限的代码重用
普遍遵循的原则不要重复自己(DRY)的目的是限制代码库的大小,从而降低出错的可能性。另一方面,开发成代码的每个抽象都引入了依赖性。随着时间的推移,抽象也经常出现必须根据特定的使用上下文进行调整。当您的微前端代码库仅限于几个功能时,开发人员不太可能试图创建这样的抽象。相反,当他们找到重用代码的机会时,他们只是复制并粘贴相关的片段,这通常比引入依赖项要好得多。
服务边界执行
系统的架构通常受某些分析和设计决策的影响。然而,决定某事和遵守这些决定往往是不一样的。在服务被拆分并就职责达成一致并记录在案之后,漂移就开始了。缺乏明确的边界或跨越边界的能力可能导致并允许开发人员破坏先前商定的设计。有一些工具,例如在 CI/CD 管道中实现的代码审查或依赖检查,但使用单独的微前端,不可能偏离约定的架构。
微前端的 6 个常见要求
为了不失去微前端的任何潜在好处,这种架构的实际实现必须满足一些共同的要求。以下六点很重要,不容忽视:
独立部署
——使用微前端的最大风险是,当它们没有正确实施时,它们将需要部署协调。除了将有意义的功能封装在单个组件中并始终确保向后兼容性的良好设计之外,组件本身必须可以一个一个地部署,而无需任何协调。
热部署
——开发某些应用程序片段的团队必须能够部署新版本而不会造成任何停机。必须考虑使用滚动更新或金丝雀部署等策略。使用带有经过深思熟虑的路径系统的高级 HTTP 路由机制可以提供很大帮助。
统一的样式/组件
——将应用程序构建为不兼容的拼贴块可能会对用户体验产生破坏性影响。如何确保视觉和行为一致性的问题必须从引入微前端的一开始就解决。该解决方案通常涵盖技术(共享 UX 库)和组织方面(共享 UX 团队)。
身份验证和授权
——显然,用户必须只进行一次身份验证。授权上下文和规则必须由前端和后端的所有组件共享。
跨组件通信
——即使组件之间的通信引入了耦合并因此应该避免,但很难想象一个应用程序由完全分离的部分组成。特定的微前端必须能够共享应用程序上下文(即用户或其他资源标识)并相互通知内部状态的变化。选择的通信方法应该更喜欢基于事件或地址栏的间接通信,而不是直接使用其他组件 API。
搜索引擎优化
——这种需求的严重程度取决于具体的用例,但对于某些应用程序来说,它是要解决的第一类公民。
微前端技术——解耦前端的 3 种方法
微前端技术可以分为三类,每一种技术都有一些优点和缺点。我们可以区分:
构建时集成——应用程序作为一个捆绑包生成,然后一次性交付给用户
服务器端集成——在提供页面的同时集成应用程序,用户浏览器获得完整的应用程序
客户端集成 – 应用程序分批交付给用户 Web 浏览器,然后集成到浏览器中
下面我们通过使用像 Strava 或 Endomondo 这样的健身追踪应用程序的示例来仔细研究这三种方法中的每一种。这些应用程序中的每一个都具有相似的特性和功能,例如显示运动员个人资料摘要、他们的最新活动、一些正在进行的挑战等的仪表板。
构建时集成
解耦前端的第一种方法是将代码库组织在独立的存储库中。通过构建时集成,每个微前端都作为独立包构建和发布。完整的应用程序导入这些包并从包含的组件组成用户界面。
这样,在组织团队和适当划分团队之间的功能上稍加努力,就可以实现合理的团队独立性。虽然它不会提供微前端的所有可能好处,例如技术多样性或部署自主性,但它的优点是它不需要任何其他工具,除了开发人员已经使用的工具。
与其他方法相比,构建时集成简化了一致性保证。这也是减少传输到用户浏览器的数据量的最简单和最有效的方法,因为整个应用程序包在构建阶段进行了优化。
在我们的示例中设计健身跟踪应用程序时需要考虑的是使用组件之间的间接通信,这将减少耦合。
服务器端集成
第二种方法的总体思路如下图所示。
浏览器对页面 (1) 的请求来自“布局服务”,该服务首先为页面布局 (2) 请求“页面模板服务”。布局包含 HTML 兼容标签,其中包含要包含的页面片段的 URL (3)。“布局服务”请求实现特定功能的所有包含部分调用服务的内容。布局服务的更高级实现并行执行查询 (4),支持故障转移和快速响应流。
在检索到所有部分 (5) 之后,准备好请求页面的全部内容并将其返回到浏览器 (6)。
布局服务在从用户角度建立应用程序的一致行为方面发挥着核心作用,但它由独立开发和部署的部分组成。
当应用程序包含由许多独立尾部组成的页面时,服务器端集成非常有用,有些是用户特定的,有些是用户之间共享的,如电子商务网站通常具有的。
有很多技术可以应用这种模式,例如服务器端包含、边缘端包含和 Zalando 的带有“片段”标签的项目 Mosaic。
服务器端包括
服务器端包含 (SSI) 是一种由 Web 服务器解释的脚本语言,用于将一个或多个文件的内容包含到网页中。语言语法基于放置在 HTML 注释中的指令,这些指令由启用 SSI 的 Web 服务器处理。
最常用的指令是“包含”,允许将一个文档包含到另一个文档中。包含的文档可以通过相对于当前文件目录的路径来引用。例如:
更强大和推荐的选项是使用虚拟参数,它可以指定任何资源,包括 CGI 脚本或远程页面:
该语言还提供变量和条件子句,以在页面上创建更多上下文感知内容。
SSI 受到流行的 Web 服务器(如 Apache 或 NGINX)的支持。
边侧包括
Edge Side Includes (ESI) 是一种用于边缘级动态 Web 内容组装的标记语言。ESI 的目标是解决 Web 基础设施扩展和内容发布的问题。与 SSI 类似,它通过 esi:include 标签提供嵌入:
条件执行命令与大量预定义变量相结合,可以在提供给用户的页面上实现真正的动态内容。
缓存代理服务器(如 Varnish 或 Squid)支持 ESI。
Zalando的马赛克项目
Mosaic 内置于 Zalando,是首批成熟的、有目的的、用于实现服务器端集成的微前端框架之一。
Mosaic 架构的中心点是“Tailor”,即在这种服务器端微前端架构中实现布局服务。为了在页面中包含微前端,使用了“片段”标签:
与普通的 SSI 或 ESI 标签相比,片段标签提供了额外的有用属性:
primary – 表示设置页面响应代码的片段
timeout – 可选的片段超时时间(以毫秒为单位)(默认为 3000)
async - 将片段推迟到正文标记的末尾
public – 防止 Tailor 将过滤后的请求标头从上游转发到片段
fallback-src – 在当前片段超时/错误的情况下回退片段的 URL
如上所述,Mosaic 旨在为微前端提供服务,并提供以下功能优势:
在后端编写预渲染标记。这对 SEO 很重要,并且可以加快初始渲染。
确保快速到达第一个字节。Tailor 并行请求片段并尽快将它们流式传输,而不会阻塞页面的其余部分。
执行绩效预算。这在其他设置中非常具有挑战性,因为没有单一的点可以控制性能。
容错:呈现有意义的输出,即使页面片段失败或超时。
如果需要更复杂的模板管理,可以简单地从文件系统或专用服务提供页面模板。
马赛克的第二部分是船长。在 Innkeeper 的陪伴下,Skipper 建立了一个先进的 HTTP 路由器,可以在需要隐藏复杂的微服务世界时使用。Skipper 本身提供了基于规则的 HTTP 请求路由,具有过滤和丰富功能。Innkeeper 用作运行时 Skipper 规则管理的 API。
服务器端集成允许从微前端轻松编写应用程序,但它不能解决需要真正丰富的前端应用程序时出现的挑战。
客户端集成
最后但并非最不重要的一点是客户端集成方法。在这里,微前端的构建是将应用程序集成到用户 Web 浏览器中。应用程序的每个部分都独立交付给浏览器,然后应用程序在呈现时被粘合。
使用这种方法,在运行时构建应用程序不需要额外的基础设施,而且它似乎是最灵活的。应用程序组件可以共享一些用户上下文,因此就像在构建时集成的那样,而不会影响微前端的其他要求。
Iframes
iframes 是一种旧的客户端集成技术,可用于将一个 HTML 文档嵌入到另一个中。在微前端的上下文中,解决方案在于使用 iframe 标记嵌入每个微前端应用程序页面布局,其中 src 属性指向为应用程序提供服务的 URL。
与这种方法中的 SSI/ESI 类似,每个微前端都可以托管在不同的地址上。与 SSI/ESI 相反,客户端浏览器负责独立下载每个片段并显示完整页面。
<br> <iframe src="http://challanges.befit.com"/><br> </body><br></html></pre> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">要成为一个成熟的微前端,嵌入在 iframe 中的应用程序应该能够与其父级通信。这可以通过使用 window.postMessage() 方法来实现,但在大多数情况下,将这样一个低级 API 与一个从微前端的角度简化集成的库包装是一种很好的做法。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">除了涵盖影响渲染内容状态的微前端之间的数据交换的标准用例之外,还需要启用父级和微前端之间的通信。后者确保 iframe 的大小适合微前端内容的大小。当 iframe 内容溢出时,必须将有关嵌入内容的实际大小的信息传播到父应用程序,并且必须由父应用程序调整 iframe 高度。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">当微前端平台本身需要基于 iframe 的集成以确保父应用程序和微前端之间的最高级别隔离时,它的效果最好。在这种情况下,可以使用任何技术或框架创建微前端,包括在客户端集成中独一无二的简单遗留应用程序集成。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">微前端的部署也不需要任何特殊的方式来构建或打包源代码。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">iframe 方法确保部署新版本的微前端不会影响其他已经部署的微前端。这种技术自由保证了整个系统不会卡在某个框架中,因为不需要微前端的兼容性。这样可以根据每个开发团队的实际业务优先级来支付技术债务。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">这种高度隔离简化了集成,但同时它会导致一些 UX 限制,在考虑您的集成解决方案时应该考虑这些限制。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">当您的主要关注点在于 UX 设计时,iframe 绝对不是最佳选择。可以提供良好的 UX 设计(在响应式网页设计的情况下也是如此),但它比其他方法稍微复杂一些。主要限制是由于微前端内容不能超出 iframe 边界。例如,显示在多个 iframe 上的弹出窗口无法正确显示。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">需要考虑的另一个因素是下载到浏览器的资源开销。特定微前端所需的每个资源(css、js等)都必须单独下载。尽管对于现在客户端使用的大多数工作站来说这可能不是问题,但请注意,仅将前端框架核心库的一个实例加载到内存中是不可能的。</p> <h3>Single SPA</h3> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br>Single SPA 是一个 JavaScript 框架,旨在构建由多个单页应用程序组成的用户界面,它承诺许多框架的共存。甚至同一框架的不同版本也可以混合在一个页面中。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">使用 Single SPA 时,每个微前端都可以独立部署。另一个不错的功能是延迟加载代码。仅在需要时才加载特定的微前端包,这提高了应用程序的加载速度。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">任何 Single SPA 应用程序的架构都包含两个概念:</p> <ulOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"> <li><p><span>应用程序</span>——微前端本身。每个应用程序都可以响应 URL 路由事件,并且必须知道如何从 DOM 中引导、挂载和卸载自己。传统 SPA 和 Single SPA 应用程序之间的主要区别在于后者必须能够与其他应用程序共存,并且不能各自拥有自己的 HTML 页面。</p></li> <li><p><span>Single SPA config</span> – 向单一 SPA 注册应用程序的 HTML 页面和 JavaScript。</p></li> </ul> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">将微前端嵌入到 Single SPA 中不需要对前端进行大量调整。新的微前端声明需要实现单个 SPA 生命周期函数并为主应用程序公开具有这些实现的文件。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">单个 SPA 生命周期函数与 React 组件生命周期函数非常相似——对象 props 具有属性 domElementGetter,返回应该放置或删除微前端的 DOM 元素。</p> <ulOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"> <li><p><span>bootstrap</span> – 将在第一次安装微前端之前执行一次。</p></li> <li><p><span>mount</span> - 将在满足激活功能条件(即正确的 URL)或手动安装微前端时执行。</p></li> <li><p><span>unmount </span>– 将在不满足激活功能条件(即不正确的 URL)或手动卸载微前端时执行。</p></li> </ul> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如何在代码中将前端应用程序标记为单个 SPA 微前端<br>如果要将前端应用程序标记为 Single SPA,第一步是准备一个主微前端文件并实现生命周期方法。这可以手动完成,但框架提供了一个方便的助手来完成它。</p> <pre data-enlighter-language="js" data-enlighter-title="File: athletes.js">import React from 'react'<br>import ReactDOM from 'react-dom'<br>import singleSpaReact from 'single-spa-react'<br>import root from './root.component.js'<br><br>const reactLifecycles = singleSpaReact({<br> React,<br> ReactDOM,<br> rootComponent: root<br>})<br><br>export function bootstrap(props) {<br> return reactLifecycles.bootstrap(props);<br>}<br><br>export function mount(props) {<br> return reactLifecycles.mount(props);<br>}<br><br>export function unmount(props) {<br> return reactLifecycles.unmount(props);<br>}</pre> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">在第二步中,您可以使用 Webpack 将您的应用程序捆绑到一个捆绑文件中,例如运动员.bundle.js,并从客户端可访问的任何服务器公开它。</p> <h4>如何在前端应用程序中使用 Single SPA 微前端</h4> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br><span>应用概念 = 单一 SPA 作为框架(The application concept = Single SPA as a framework)</span></p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">第一步是在根应用程序中注册一个微前端。为此,您应该使用以下功能:</p> <pre data-enlighter-language="js">registerApplication(<br> appName: string,<br> applicationOrLoadingFn: () => <Function | Promise>,<br> activityFn: (location) => boolean,<br> customProps?: Object<br>);</pre> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"> </p> <ulOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"> <li><p>appName – 将在单水疗中用作标识符的名称</p></li> <li><p>applicationOrLoadingFn – 一个可以返回应用程序或应用程序承诺的函数</p></li> <li><p>activityFn – 一个函数,当必须安装应用程序时返回 true,当必须卸载应用程序时返回 false。</p></li> <li><p>customProps – 一个可选对象,无论何时调用它们都会传递给生命周期方法。</p></li> </ul> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">最后一步是 start() 单一 SPA 引擎,然后一切就绪。</p> <pre data-enlighter-group=" File: root.js" data-enlighter-language="js" data-enlighter-title=" File: root.js">import {registerApplication, start} from 'single-spa';<br><br>const domElementGetter = () => document.getElementById('micro-font-end-container');<br>const pathPrefix = (prefix) => {<br> return (location) => location.pathname.startsWith(`${prefix}`);<br>}<br><br>registerApplication('athletes', () => import ('athletes.bundle.js'), <br>pathPrefix('/athletes'), {domElementGetter});<br>registerApplication('challenges', () => import ('challenges.bundle.js'), <br>pathPrefix('/challenges'), {domElementGetter});<br>start();<br></pre> <pre data-enlighter-group="File: index.html" data-enlighter-language="html" data-enlighter-title="File: index.html"><html><br><body><br> <script src="/dist/root.js"></script><br> <a onclick="singleSpaNavigate('/athletes')">Go to athletes</a><br> <a onclick="singleSpaNavigate('/challenges)">Go to challenges</a> <br> <div id="micro-font-end-container"><br> //i.e. here micro frontends can be injected<br> </div><br></body><br></html></pre> <h4>包裹概念 = 作为库的单一 SPA (The parcel concept = Single SPA as a library)</h4> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br><span>当使用 Single SPA 作为框架时,容器应用程序是一个简单的应用程序容器</span>,这些应用程序会根据根更改进行切换。另一种选择是包裹概念。在这里,您在任何框架中创建一个容器应用程序作为系统的基础,并且必须将包(或实际上是微前端)直接安装在特定位置。这样一页可以包含多个微前端。这更接近于将用户界面构建为解耦特征的组合,但同时可见和可访问的概念。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">包裹也应该在正确的时间卸载。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">在下面的示例中,使用 React 作为主要框架,因此 componentDidMount 和 componentWillUnmount 可用于挂载和卸载包裹。</p> <pre data-enlighter-language="js">class AthletesMicrofrontendComponent extends React.Component {<br><br> componentDidMount() {<br> SystemJS.import('athletes.bundle.js')<br> .then(athletesApp => {<br> const domElement = document.getElementById('athelete-micro-frontend-id');<br> mountParcel(athletesApp, {domElement})<br> });<br> }<br><br> render(){<br> return <div id="athelete-micro-frontend-id"></div><br> }<br> ...<br>}</pre> <h1>微前端方案比较</h1> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br>下表总结并强调了每种方法的主要优势和劣势:</p> <table interlaced="enabled" data-sort="sortDisabled"> <tbody> <tr> <td width="4"><span>技术</span></td> <td width="25.666666666666668"><span>类别</span></td> <td width="72.66666666666667"><span>例子实现</span></td> <td width="133.66666666666666"><span>优势</span></td> <td width="94.66666666666667"><span>弱势</span></td> <td width="157.66666666666666"><span>建议</span></td> </tr> <tr> <td width="4"><span>构建时的包</span></td> <td width="7.666666666666668"><span>构建时集成</span></td> <td width="72.66666666666667"><span>NPN, yarn</span></td> <td width="133.66666666666666"><p><span>易于设置 - 无需额外工具</span></p><p><br><span>为开发者所知</span></p><p><span>代码重复数据删除</span></p><p><span>轻松实现 UX 一致性</span></p></td> <td width="11"><p><span>锁步释放过程——必须重新编译和部署整个包</span></p><p><br><span>仅限于一个框架</span></p></td> <td width="136.66666666666666"><span>仅在其他选项似乎非常复杂时才用于小型项目(不超过三个团队)</span></td> </tr> <tr> <td width="42.66666666666667"><span>SSI/ESI</span></td> <td width="7.666666666666668"><span>服务器端集成</span></td> <td width="51.66666666666667"><span>SSI – NGINX, Apache Http</span><p><span> </span></p><p><span>ESI – Varnish, Squid</span></p></td> <td width="133.66666666666666"><p><span>易于设置——HTTP 服务器和 Cashes 是每个 Web 应用程序架构的一部分</span></p><p><br><span>部署完全独立</span></p></td> <td width="11"><p><span>缺乏跨组件通信——必须以其他方式解决</span></p><p><br><span>难以实现一致的用户体验观感</span></p><p><span>缺乏内置的身份验证和授权</span></p></td> <td width="136.66666666666666"><span>当应用程序和服务架构波动较小的微服务时,用于电子商务等 Web 应用程序</span></td> </tr> <tr> <td width="4"><span>专业的微前端中间件</span></td> <td width="7.666666666666668"><span>服务器端集成</span></td> <td width="51.66666666666667"><span>Zalando’s Mosaic, </span><p><span> </span></p><p><span>Compoxure, micro-fe</span></p></td> <td width="133.66666666666666"><p><span>部署完全独立</span></p><p><br><span>对页面性能和故障转移的出色控制</span></p><p><span>具有自动发现功能的内置高级动态路由</span></p></td> <td width="11"><p><span>难以设置——需要额外的组件</span></p><p><br><span>缺乏跨组件通信——必须以其他方式解决</span></p><p><span>难以实现一致的用户体验观感</span></p><p><span>缺乏内置的身份验证和授权</span></p></td> <td width="136.66666666666666"><span>当应用程序和服务架构波动较大的微服务时,用于类似 Web 应用程序的电子商务</span></td> </tr> <tr> <td width="4"><span>Iframes</span></td> <td width="7.666666666666668"><span>客户端集成</span></td> <td width="51.66666666666667"><br></td> <td width="133.66666666666666"><span>易于设置 - 无需额外工具</span><p><span> </span></p><p><span>部署完全独立</span></p><p><span>高组件隔离</span></p><p><span>跨组件通信</span></p><p><span>真正的框架不可知论者</span></p></td> <td width="11"><p><span>难以实现深度链接</span></p><p><br><span>难以实施 RWD</span></p><p><span>高资源消耗</span></p></td> <td width="136.66666666666666"><span>当框架不可知和组件隔离是关键问题并且 UX 不是那么重要时使用</span></td> </tr> <tr> <td width="4"><span>微前端框架</span></td> <td width="7.666666666666668"><span>客户端集成</span></td> <td width="51.66666666666667"><span>Single SPA</span></td> <td width="112.66666666666667"><p><span>微前端和容器应用程序之间的完全集成</span></p><p><br><span>支持所有主要的 JS 框架</span></p><p><span>延迟加载</span></p></td> <td width="11"><span>没有充分记录的引擎</span></td> <td width="136.66666666666666"><span>在由许多通信微前端组成的丰富应用程序中使用</span></td> </tr> </tbody> </table> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"> </p> <h1>概括</h1> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br>如果你想充分利用你的微服务架构,微前端模式似乎真的是拼图中缺失的一块。根据您的需求,确切的解决方案可能会有所不同。例如,对于电子商务网站,您可以选择任何类型的服务器端集成。但是,当您的目标是高级覆盖应用程序时,其中一种客户端技术将是您更好的解决方案。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如果您认为微前端仍然会带来太多麻烦,那么至少选择构建时模块化。从长远来看,它总是会得到回报。</p> <pOpen Sans", sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如果您对微前端及其实现有任何经验,请在下面分享。我们很乐意收到您的想法和疑虑,并进一步讨论该主题。</p> <p> <mpprofile data-pluginname="mpprofile" data-id="MzkxOTE2NzExOA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/OdhAGTZXQDnJrYxhzToc5fBroJib8SKJwEQAlNQibUUYiaIDHFRqibpugPgNLVpNbWkvEaSrxl4f6Yj5y9MwGqru8A/0?wx_fmt=png" data-nickname="超级工程师" data-alias="ceo_chief_engr" data-signature="前端后端一锅端,数据物联区块链,AI AR 和VR,分析 安全 元宇宙。全栈开发Java,Python,Go,Groovy,Kotlin,C#,Node,TypeScript,JavaScript,Rust, Swift,R,Ruby。" data-from="0"></mpprofile> </p> <p> <mpprofile data-pluginname="mpprofile" data-id="MzAxMTAxMDMxNQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/DKy0HOKSSPO78yECb5uCibHlrbK18sG7HyN0VeBVC2XByJHn16ejbsYkH91lhrqs7qF4AIQKplDlZibearmtyibjA/0?wx_fmt=png" data-nickname="CIO和CTO" data-alias="cxo_cio_cto" data-signature="作为企业高管CIO,CDO,CTO的助手,介绍科技趋势,资讯,商业案例,技术实现。 如数字化转型,5G,量子,物联网,云计算,生物科技,隐私计算,虚拟现实,区块链,移动,人工智能,智能设备,机器人,大数据,数据分析,数据智能等." data-from="0"></mpprofile> </p> <p> <mpprofile data-pluginname="mpprofile" data-id="MzA5NDQzMDQ0MA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/iaAAA5YN044EBcTrLicFhAsm1Y8zeFpdKQlNiamKQHlWRMb4HPhRafYJbtUBpxzGE31OvzV0B9IWVoe0N7yAoUWWw/0?wx_fmt=png" data-nickname="首席数字化转型官" data-alias="cdto-cdo" data-signature="交流企业的数字化转型,创新和整合。帮助CIO,CDO,CDTO成长。关注企业数字化方法,流程,框架,案例以及趋势。探讨企业的业务架构规划设计,企业的IT建设和数字化推进。" data-from="0"></mpprofile> </p> <p> <p> <p> <p> <p> <p> <p> <p> <p><br></p> </p> </p> </p> </p> </p> </p> </p> </p> <p> <p> <p> <p> <table> <tbody> <tr> <td valign="top" colspan="1" rowspan="1"><span>本文</span></td> <td valign="top" colspan="2" rowspan="1"><span>https://jiagoushi.pro/micro-frontends-missing-piece-puzzle-feature-teams</span></td> </tr> <tr> <td valign="top" colspan="3" rowspan="1"><span>讨论:知识星球【首席架构师圈】或者加微信小号【cea_csa_cto】或者加QQ群【<span>792862318</span>】</span></td> </tr> <tr> <td width="53" valign="top" height="118"><span>公众号<br><br></span></td> <td width="231" valign="top" height="118"><span>【jiagoushipro】<br>【超级架构师】<br>精彩图文详解架构方法论,架构实践,技术原理,技术趋势。<br>我们在等你,赶快扫描关注吧。</span></td> <td width="205" valign="top" height="118"><img data-ratio="1" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/82ae9d00j00r6bthv0004d2009k009kg009k009k.jpg" data-type="jpeg" data-w="344"></td> </tr> <tr> <td width="53" valign="top" height="206"><span>微信小号<br><br></span></td> <td width="231" valign="top" height="206"><span>【cea_csa_cto】<br>50000人社区,讨论:企业架构,云计算,大数据,数据科学,物联网,人工智能,安全,全栈开发,DevOps,数字化.<br><br></span></td> <td width="205" valign="top" height="206"><p><img data-ratio="1" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/50cefba2j00r6bthv000od200by00byg00by00by.jpg" data-type="jpeg" data-w="430"></p></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1" width="53"><span>QQ群<br><br></span></td> <td valign="top" colspan="1" rowspan="1" width="231"><span><span>【792862318】</span>深度交流企业架构,业务架构,应用架构,数据架构,技术架构,集成架构,安全架构。以及大数据,云计算,物联网,人工智能等各种新兴技术。<br><span>加QQ群,有珍贵的报告和干货资料分享。</span></span></td> <td valign="top" colspan="1" rowspan="1"><p><img data-croporisrc="https://mmbiz.qlogo.cn/mmbiz_jpg/RPNNugBqYDq9ibf9qyoeHJh72gtXX01VsVVMs61A7AKmRsLPXa2Bob0zypzeN81oNUGiawIK8VGLh4q9nJ97ThFw/0?wx_fmt=jpeg" data-cropx1="0" data-cropx2="720" data-cropy1="167.01030927835052" data-cropy2="1161.6494845360826" data-ratio="1.3819444444444444" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/d7b44b2bj00r6bthw0027d200k000rng00k000rn.jpg" data-type="jpeg" data-w="720"></p><p><br></p></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1" width="53"><span>视频号</span></td> <td valign="top" colspan="1" rowspan="1" width="231"><span>【<span>超级架构师</span>】<br>1分钟快速了解架构相关的基本概念,模型,方法,经验。<br>每天1分钟,架构心中熟。</span></td> <td valign="top" colspan="1" rowspan="1"><p><img data-croporisrc="https://mmbiz.qpic.cn/mmbiz_png/RPNNugBqYDrz2M0lhNaFxQnncic0Y9CgwKibrUia8sLxpT7UGicQ24Mbtxx6ILBgqotKDDTXE2NbZ0Thg5XrxOib3Gw/640?wx_fmt=png" data-cropx1="4.8" data-cropx2="492" data-cropy1="108" data-cropy2="705.6" data-ratio="1.2254098360655739" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/2554abf5j00r6bthw0016d200dk00gmg00dk00gm.jpg" data-type="jpeg" data-w="488"><br></p></td> </tr> <tr> <td width="51" valign="top"><span>知识星球</span></td> <td width="231" valign="top"><span>向大咖提问,近距离接触,或者获得私密资料分享。</span></td> <td width="205" valign="top"><br><p><img data-ratio="1" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/9c1e5bcfj00r6bthw000vd200by00byg00by00by.jpg" data-type="jpeg" data-w="430"></p></td> </tr> <tr> <td width="53" valign="top"><span>喜马拉雅</span></td> <td width="231" valign="top"><span>路上或者车上了解最新黑科技资讯,架构心得。</span></td> <td width="205" valign="top"></td> </tr> <tr> <td width="53" valign="top"><span>知识星球</span></td> <td width="231" valign="top"><span>认识更多朋友,职场和技术闲聊。</span></td> <td width="205" valign="top"></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1"><span>微博</span></td> <td valign="top" colspan="1" rowspan="1"><span>【智能时刻】</span></td> <td valign="top" colspan="1" rowspan="1"></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1"><span>哔哩哔哩</span></td> <td valign="top" colspan="1" rowspan="1"><span>【<span>超级架构师</span>】</span></td> <td valign="top" colspan="1" rowspan="1"><p><img data-ratio="1" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/77b0bf08j00r6bthx000xd200by00byg00by00by.jpg" data-type="jpeg" data-w="430"></p></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1"><span>抖音</span></td> <td valign="top" colspan="1" rowspan="1"><span>【cea_cio】<span><span>超级架构师</span></span></span></td> <td valign="top" colspan="1" rowspan="1"><p><img data-ratio="1.4933333333333334" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/41f65b91j00r6bthx0023d200ku00v4g00ku00v4.jpg" data-type="jpeg" data-w="750"></p></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1"><span>快手</span></td> <td valign="top" colspan="1" rowspan="1"><span>【cea_cio_cto】<span>超级架构师</span></span></td> <td valign="top" colspan="1" rowspan="1"><p><img data-ratio="1" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/576d7645j00r6bthx000xd200by00byg00by00by.jpg" data-type="jpeg" data-w="430"></p><p><br></p></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1"><span>小红书</span></td> <td valign="top" colspan="1" rowspan="1"><span>【cea_csa_cto】</span><span><span>超级架构师</span></span></td> <td valign="top" colspan="1" rowspan="1"><br><p><img data-ratio="1" data-s="300,640" src="http://dingyue.ws.126.net/2022/0127/6e257fc1j00r6bthy000xd200by00byg00by00by.jpg" data-type="jpeg" data-w="430"></p></td> </tr> <tr> <td valign="top" colspan="1" rowspan="1"><br></td> <td valign="top" colspan="1" rowspan="1"><br></td> <td valign="top" colspan="1" rowspan="1"><br></td> </tr> </tbody> </table> </p> <p> <span>谢谢大家关注,转发,点赞和点在看。</span> </p> </p> </p> </p> </div> </body> </html> </p> </body> </html>
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.