跳过主要内容

微前端是什么?如何工作

了解微前端是什么,比较核心架构模式,了解权衡,了解如何在Capacitor和Electron应用中应用该方法。

微前端是什么?它是如何工作的?

微前端是什么?它是如何工作的? 2016, 和一个 2024 ,并且 23.6% 调查显示 75.4% in 2022. 在

State of Frontend数据中

你可能已经遇到这个问题了。三个产品团队共享一个前端仓库,等待同一个发布列车,即使一个团队正在修改结账,另一个团队正在更新资料,第三个团队正在调整营销页面。微前端架构将这些产品区域分开,使团队可以独立拥有、测试和发布它们,同时用户仍然体验到一个应用。 这点很重要。微前端不是更小的文件夹、组件或包。它的核心目的在于组织和发布的独立性

,由技术边界来支持,使拥有权变得明确。这种架构可以消除协调瓶颈,但也会引入运行时集成、依赖管理、测试、安全和性能的责任。

理解微前端概念

从一个前端到多个拥有的应用

A传统的前端通常只有一个仓库,一个构建,和一个部署边界。即使code被分成干净的特性文件夹,那些文件夹背后的团队仍然可能依赖于相同的管道和发布计划。一个小的变化在一个区域可以触发整个应用程序的构建,共享的回归测试,和每个团队的协调。

A微前端将浏览器应用程序分成 业务能力。checkout团队拥有checkout, profile团队拥有账户设置,和marketing团队拥有促销内容。每个片段可以有自己的代码库,交付过程,和发布节奏,然后通过一个壳或组合层成为一个更大的体验。

马丁福勒定义了模式为 “一个架构风格,其中独立可交付的前端应用程序被组合成一个更大的整体” 在他的基础 微前端架构指南中。这个短语“独立可交付”比“前端应用程序”更有权重。没有独立的部署边界,你可能会有一个模块化的砖块而不是一个微前端系统。

一组疲劳的办公室工人坐在桌子上,手里拿着纸张,代表着不同的微前端开发团队在办公室。

一个组合商店的类比

想象一下一家百货商店。一个团队负责门店前台,另一个团队负责收银台,另一个团队负责退货。顾客看到的是一家商店,但每个区域都有不同的流程、责任和人员。微前端工作方式类似:浏览器渲染一个产品体验,而几个团队在幕后操作不同的界面区域。

通常,应用程序壳拥有共享的框架、导航、身份验证上下文和路由决策。微前端拥有该框架内的页面或功能。团队同意了他们之间的界限,但不需要共享每个实现细节。

这个术语与2016年11月Thoughtworks在其技术雷达中突出了它之后,才与浏览器相关联。 微服务思维到浏览器 为了更广泛地了解可扩展的Web开发,Nerdify的文章中提供了一个更实用的概述,比较该模式与邻近的方法,如插件架构,这个主题在本 插件架构指南中讨论插件架构指南 scalable web development.

微前端不是每个界面都需要的升级。只有当团队边界和发布边界造成了真正的痛苦时,微前端才有意义。只有当这种独立性值得管理更多的合同、资产、运行时故障模式和运营工具时,成本才会得到合理化。

微前端架构是如何工作的

壳和碎片

一个工作系统通常从一个 应用壳也称为容器或调度器。壳渲染公共布局、建立路由、提供身份验证上下文和共享界面元素,如导航或通知。它还决定了哪个微前端应该加载以及该碎片应该挂载到的位置。

每个碎片都是一个独立维护的应用。它可能在一个单独的仓库中存活、使用自己的CI管道、发布自己的版本并暴露一个捆绑包、碎片、Web组件或远程模块。壳在浏览器中组合这些片段,可能是在页面加载时或当一个路由需要它们时。

一个图表,展示了微前端架构中应用壳连接到购物车、用户头像和喇叭组件的示意图。

边界只有在团队可以依赖它时才有意义。壳和每个碎片都需要一个明确的合同,涵盖挂载行为、路由所有权、加载状态、错误处理、设计令牌、可访问性期望和支持的依赖版本。

实践规则: 分享契约和视觉原语。不要因为两个团队目前使用相同的框架而仅仅分享运行时实现细节。

不再重建单体

片段有时需要通信。一个结帐片段可能需要知道用户已登录,而一个个人资料片段可能需要发布一个已更新账户事件。团队可以使用自定义浏览器事件、共享存储、URL参数或注入服务。

每个选项都创建了一个不同的耦合配置:

  • 自定义事件 保持所有权分开,但团队必须记录事件名称、数据包形状和时间。
  • 共享存储 简化协调状态,但它们可以重建架构旨在减少的中央依赖图。
  • URL参数 适用于导航和可共享状态,但它们并不适合每种交互。
  • 注入服务 提供受控能力,但壳必须维护那些服务合同。

应用壳只应协调整个应用的部分。若它负责每个片段的状态和业务规则,它就变成了一个更复杂的部署过程的分布式单体。

福勒的历史进展解释了为什么该模式经常与微服务进行比较。两种方法都分离了所有权和交付,但微前端将这种独立性应用到了浏览器界面。在当前的工具中 模块联邦的使用变得更加普遍,而单页应用仍然是团队选择基于生命周期的应用注册的orchestration选项。 例如,checkout团队可以在不重建目录片段的情况下发布支付流程修复。目录团队可以继续以较慢的发布频率,因为壳会根据其运行时配置加载每个批准的片段。独立的交付边界,而不是可视化的分离组件的外观,是该架构的主要收益。

评估周围平台的团队还需要考虑

前端系统的应用基础设施 因为仓库和框架本身无法提供可靠的组合。比较核心微前端模式

比较核心微前端模式

模式

隔离 Isolation 整合模型 共享依赖 性能 最佳匹配
iframe 强隔离和文档隔离 嵌入式文档与跨框架消息 默认不隔离 可能增加加载和通信延迟 不受信任、遗留或高度隔离的体验
Web 组件 封装的元素和使用时的 Shadow DOM 样式 使用壳层挂载的自定义元素 共享的设计令牌和浏览器API 通常预测性,但取决于组件的重量 遵循标准的团队需要框架的灵活性
模块联邦 中等级别的运行时隔离 在运行时加载和挂载远程模块 明确的协商或捆绑依赖 当加载和去重是受控的时,效率很高 紧密集成的应用程序,具有独立的发布
single-spa orchestration边界而不是完整的隔离模型 通过生命周期钩子注册的应用 依赖于应用和根配置 依赖于加载规则和框架组合 基于路由的多框架协调

iframe

在比较中,iframe提供了最强的隔离。嵌入的应用有自己的文档、样式和 JavaScript 环境,因此不会意外地改变宿主页面的 DOM。跨窗口消息可以创建一个受控的通信路径。

隔离使 iframe 对于遗留系统、合作伙伴体验或必须保持独立的内容非常有用。然而,成本出现在响应式布局、导航、可访问性、焦点管理和共享身份验证中。一个 checkout iframe 可能会感觉像一个外国表面,如果宿主和嵌入应用没有仔细协调。

web 组件

web 组件使用浏览器标准,而不是要求每个团队采用相同的框架。自定义元素定义了一个稳定的挂载表面,Shadow DOM 可以限制样式泄露。shell 还需要处理应用路由、加载状态、错误边界和共享设计令牌。

当团队想要框架灵活性而不必让浏览器加载每个片段的整个应用运行时,这个选项很好用。它并没有自动解决依赖大小、状态通信或治理问题。一个自定义元素仍然可以包含一个具有自己的操作复杂性的大应用。

模块联邦

模块联邦(Module Federation),在Webpack 5中引入,支持工具如Vite和Rspack,能够在运行时从远程入口加载编译好的模块。它提供了紧密的集成,使共享组件和协调的导航感觉更加自然,尤其是在使用iframes时。

这种便利性带来了责任。团队需要兼容的公开接口、共享依赖项的规则、远程版本管理和恢复计划,当一个远程无法加载时。 单体和微服务架构之间的差异 提供了有用的上下文来分离部署独立性和简单的code分解。

单页应用(single-spa)

单页应用(single-spa)作为一个框架无关的调度器。团队注册应用和生命周期钩子,然后根配置根据路由或其他条件激活它们。它可以协调使用不同框架构建的应用,但它并没有消除对契约、依赖项政策、性能预算或安全控制的需求。

团队可以结合这些机制。例如,单页应用根可能协调路由,模块联邦可能提供远程模块,web组件可能定义公共挂载表面。这种结合可以很强大,但每增加一个层次都会增加开发者必须理解和测试的行为数量。

利弊和隐含风险

微前端将决策推向边界。它们可以减少发布的爆炸半径并给团队更多控制,但系统必须管理更多的艺术品、合同和运行时条件。

维度 好处 交易/隐含风险
团队自主权 团队拥有从头到尾的业务切片 团队必须维护独立的管道、on-call所有权和发布纪律
部署 一个片段可以不重建整个界面而发布 发布变成非原子性的,因此不兼容的版本可能在生产中相遇
故障隔离 一个失败的远程可以通过fallback来包含 糟糕的错误边界仍然可以使导航或关键旅程不可用
性能 懒加载和较小的初始包可以帮助常见流程 更多请求,重复的框架 code 和远程初始化可以损害运行时性能
技术选择 团队可以在允许的边界内使用不同的框架 调试、可访问性、设计一致性和招聘变得更加困难
安全 边界可以限制直接实施共享 壳可能会执行它没有充分验证的远程 code
治理 共享标准可以保留一致的产品 设计系统、依赖规则、契约和平台支持需要持续的协调

性能账单

独立的片段通常会单独构建资产。没有细心的加载规则,浏览器可能会请求更多的文件,初始化更多的code,或者下载重复的框架依赖项。微前端的性能指导强调按需加载、谨慎依赖共享、模块级缓存和故障隔离。

实用的设计从现有的应用程序开始,建立一个基线。测量路由启动、捆绑组合、远程加载、初始化和用户可见的故障。然后为壳和每个高流量片段设置预算。懒加载只有在应用程序不阻塞关键旅程时,才会有帮助,尤其是在长链条上的远程模块上。

安全性在接口处

远程模块并不是因为它有一个单独的仓库而自动安全的。壳可能会执行它没有验证的code,前端界限并不能代替API或令牌服务的授权。 安全性为重点的微前端分析 强调了信任、签名、完整性检查和授权需要在团队分发运行时code之前进行设计的注意事项。

版本不一致创建了另一个风险类别。片段可能会单独工作,但在遇到不同版本的壳、共享库、设计令牌集或事件载荷时会失败。 Nx的架构指导 识别协调、环境配置、应用效率和可重用性作为持续挑战。

架构并不会删除协调。它将协调从发布会议转变为合同、自动化、可观察性和治理。

团队还需要对共享依赖项、可访问性审查、事件响应和回滚决策拥有明确的所有权。如果没有人拥有平台层,每个产品团队都会以不同的方式解决组合,用户将经历的结果一致性会被视为一个损坏的应用。

测试部署和迁移实践

测试必须反映应用程序的运行方式。一个通过单元测试的片段仍然可能在壳提供了一个改变的路由、一个意外的身份验证状态或一个不同的共享依赖项时失败。

构建层次化的测试系统

从每个片段的孤立测试开始。这些测试验证渲染、商业规则、键盘行为、加载状态和本地错误处理不需要完整的壳。

合同测试位于它们之上。它们验证壳和片段之间的接口,包括挂载输入、路由模式、发出的事件、期望的负载、身份验证假设和fallback行为。合同测试应该在生产之前失败,如果一个团队改变了另一个团队消费的接口。

shell集成测试然后加载真实的片段艺术品在一个代表性的组合中。它们应该涵盖路由、身份验证转换、共享导航、加载失败和版本 combination。端到端测试属于顶部,因为它们验证完整的旅程,如浏览产品、登录和完成结账跨多个独立交付的片段。

一个图表说明了微前端测试金字塔,包括隔离的片段测试、合同测试、shell集成和端到端旅程。

控制发布面板

使用版本化清单,使shell可以识别它加载的确切片段艺术品。清单还给运营者提供了一个地方来固定一个已知好的版本,当远程发布引起错误时。

有用的控制包括:

  • 功能标志: 激活一个新片段给内部观众或选择的路线之前广泛曝光。
  • 金丝雀发布: 将有限的观众指向新艺术品,同时监测浏览器错误、加载失败和关键业务动作。
  • 可观察的捆绑包: 将发布标识符添加到日志、跟踪和客户错误中,使负责团队可以识别失败的片段。
  • 回滚路径: 保持兼容的前身 artifact 可用,并将回滚转换为操作动作,而不是手动重建。

团队应在生产环境中测试 shell 和 fragment,确保内容交付路径、缓存、身份验证令牌和远程清单在用户端正确工作。 部署自动化实践 可以支持可重复的推广和回滚工作流程,但架构仍需要明确的所有权。

逐步迁移一个域名

迁移路由器迁移一项功能从 monolith 到新 fragment,同时其他部分保持不变。特性开关可以支持并行运行,允许团队在新路径与现有实现之间进行比较,然后将新路由设为默认。

考虑一个商业应用程序,分为独立的目录、账户和结算团队。shell 拥有导航和身份验证,目录团队拥有产品浏览,账户团队拥有配置文件设置,结算团队拥有购物车和支付流程。每个团队发布自己的 artifact,而合同测试保护路由和事件协议。

从低风险域名开始,发布它并在真实的旅程中观察它。只在团队可以在不要求整个组织协调发布的情况下部署、诊断和回滚该片段时才扩展。

在 Capacitor 和 Electron 中使用微前端

A Capacitor 或 Electron 应用程序添加了另一个 shell,围绕着浏览器 shell。 Capacitor 将 web code 放置在一个原生移动 WebView 中,而 Electron 运行 web code 在桌面渲染器进程中。在两种情况下,应用程序可以加载一个本地 shell,用于在运行时获取所选前端 artifact,而不是将每个界面变化嵌入到原生二进制中。

这种安排创造了一个有用的发布分离。原生能力、权限和桥接 code 与安装的应用程序绑定在一起,而 web 所有权的表面,如账户、帮助、目录或设置,可以遵循一个独立的交付路径。shell 还需要决定哪些碎片来自哪里、哪个版本是批准的,以及如果 fetch 或验证步骤失败时应用程序应该做什么。

实时更新和回滚

实时更新系统必须将前端 artifact 视为可发布的软件。它应该交付 签名包并在激活之前验证它们,支持阶段性发布的发布渠道,在下一次启动时应用更新,而不是中断活动会话,并提供自动回滚保护,具有原子重置。

这些控制映射自然到微前端交付。一个移动或桌面 shell 可以固定一个清单,获取一个兼容的碎片,验证其签名,并在完整包可用时激活它。如果下一次启动检测到失败,更新器可以恢复到先前的已知良好状态,而不是留下用户使用一个部分更新的界面。

Capgo 是此交付模型的一种选择。它为 CapacitorJS 和 Electron 应用程序提供了一个实时更新平台,发布了签名的 Web 包,支持目标渠道,应用下一次启动时更新,并提供日志,版本历史,采用率和失败指标,回滚保护,CI/CD 集成,以及一个 API。 了解 Capacitor 如何连接 Web 和本机 code.

使用 Capacitor 或 Electron 本机应用程序壳来实现微前端的示意图

本地壳中的变化

本地壳引入了浏览器应用可能不面临的约束:

  • 连接性: 当设备脱机时,可能会出现碎片不可用,因此壳需要缓存的艺术品或本地fallback。
  • 兼容性: Web 包可能依赖于本机桥行为,但安装的二进制文件不支持。
  • 安全性: 远程 code 必须在应用程序上下文中进行身份验证,完整性检查和授权。
  • 恢复: 必须让 shell 能够拒绝无效的包并恢复一个工作的版本而不需要立即分发存储。
  • 会话安全性: 在支付或表单流程中更新可能会导致不一致的状态,因此下次启动激活比中断活动工作更安全。

这个模型增强了回滚功能,当交付平台提供原子激活和详细的发布指标时。它会使架构更加复杂,当团队认为 Web 独立性消除了原生兼容性规划的需求时。原生 shell 仍然是合同边界,所有碎片都必须尊重它。

何时选择微前端

选择微前端时 独立部署是真正的需求几个小组拥有明确分离的产品表面,或遗留和新接口必须在长期迁移期间共存。技术多样性也可以证明模式的必要性,当团队需要框架边界而单个构建无法清洁地适应时。

避免它,当一个小团队可以舒适地拥有一个前端,域共享广泛的可变状态,或您的组织缺乏可靠的 CI、可观察性、合同测试和回滚程序。一个分布式接口没有这些基础并不创造自主性。它创造了更多的失败地点。

使用一个简单的起始测试:

  • 拥有权: 一个团队是否可以为提议的片段做出决定?
  • 边界: 壳和片是否可以通过稳定的契约进行通信?
  • 发布需求: 团队是否需要独立部署?
  • 运营准备: 是否可以监控、测试、固定和回滚片段?
  • 用户价值: 是否会通过拆分提高交付速度而不损害性能或一致性?

从低风险区域开始,如帮助内容或设置。定义挂载契约、路由所有权、事件、设计令牌、fallback行为和版本策略。通过特性标志发布,测量添加的包和加载成本,并记录每个新渠道、清单、依赖规则和回滚路径。

微前端是组织和发布独立性工具,而不是自动提高前端质量的方法。如果发布问题较小,模块化单体可能是更好的答案。如果协调问题大且持久,经过严格管控的微前端架构可以给团队提供所需的自治权。


如果您正在评估微前端用于Capacitor或Electron产品 Capgo 可以帮助您通过受控的通道分发签名的Web包,激活下一次启动的更新,并通过回滚保护恢复。访问Capgo以查看其分发、可观察性和API选项,然后设计您的碎片发布流程。

Capacitor应用的实时更新

当web层bug实时更新时,通过Capgo将修复推送给用户,而不是等待几天的app store审批。用户在后台接收更新,而本地变化仍在正常审批路径中。

来自马丁的人工支持

立即开始

最新博客文章

Capgo为您提供了创建真正专业的移动应用所需的最佳见解。