跳过主要内容

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

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

微前端是什么和它如何工作

微前端是一种由独立拥有和可部署的前端应用组成的用户界面。这种方法是 Thoughtworks 在 2016,并且一项 2024 调查显示 23.6% 的受访者在前一年使用过微前端,相比于 75.4% 的 2022. 前端数据

你可能已经遇到这个问题了。三个产品团队共享一个前端仓库,等待同一个发布流程,即使一个团队正在修改结帐,另一个团队正在更新资料,第三个团队正在调整营销页面。微前端架构将这些产品区域分开,使团队可以独立拥有、测试和发布它们,同时用户仍然体验到一个应用。

那一點很重要。微前端不是更小的文件夾、組件或套件。它的核心目的在於 組織和發佈的獨立性, 由技術界限支持,明確了擁有權。該架構可以移除協調瓶頸,但也引入了運行時整合、依賴管理、測試、安全性和性能責任

目錄

了解微前端概念

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

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

微前端将浏览器应用分成 业务能力. 检出团队拥有检出,配置文件团队拥有账户设置,营销团队拥有促销内容. 每个片段都可以有自己的代码库,交付过程,发布节奏,然后成为更大体验的一部分通过一个 shell 或组合层.

马丁·福勒定义了模式 一个独立可交付的前端应用程序的架构风格,通过组合它们来构成更大的整体 在他的基础 微前端架构指南微前端的概念是指独立可部署的前端应用。没有独立的部署边界,你可能会得到一个模块化的单体应用,而不是微前端系统。

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

一个组合商店的类比

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

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

这个术语与扩展 微服务思维到浏览器 Thoughtworks 在 2016 年 11 月的技术雷达中突出了它。Fowler 后来记录了它从评估到试验,然后采用,这描述了模式从新兴技术向更为成熟的架构选项的发展。关于 可扩展的 Web 开发的更广泛实用概述 ,它有助于将模式与相邻的方法进行比较,例如插件架构,这在本文中进行了讨论 插件架构指南.

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

微前端架构的工作原理

壳和碎片

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

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

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

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

实践规则: 共享合同和视觉原语,谨慎地避免共享运行时实现细节,仅因为两个团队当前使用相同的框架。

不重建单体的沟通

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

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

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

shell 应该只协调属于整个应用程序的部分。如果它负责每个片段的状态和商业规则,它就变成了一个更复杂的部署过程的分布式大型应用程序。

Fowler 文档的历史进程解释了为什么该模式经常与微服务进行比较。两种方法都分离了所有权和交付,但微前端将这种独立性应用于浏览器界面。在当前工具中 模块联邦使用 已成为突出的选项,而单-SPA 仍然是团队希望基于生命周期的应用程序注册的协调选项。

例如,结账团队可能会发布一个支付流程修正,而不需要重建目录片段。目录团队可以继续以较慢的发布节奏,因为 shell 根据其运行时配置加载每个批准的片段。独立的交付边界,而不是可视化的分离组件的外观,是该架构的主要收益。

评估周围平台的团队也需要考虑 前端系统的应用程序基础设施因为仓库和框架本身无法提供可靠的组合。

比较核心微前端模式

微前端并没有一个通用的集成机制可以解决所有问题。选择合适的集成机制需要比较隔离、通信、依赖共享、浏览器行为和运维所有权等因素,而不是选择最时尚的工具。

模式 隔离 上下文:Capgo Builder / 原生云构建产品页面。角色:短的UI标签或导航项。见于:页面native-build.astro。消息键`native_build_v2_trust_iso_lbl` (Native Build V2 Trust Iso Lbl)。 集成模型 共享依赖 性能
Iframes 最佳匹配 iframe 强大的过程和文档隔离 嵌入式文档跨框架消息传递 不受信任、遗留或高度隔离的体验
Web 组件 封装的元素和,使用时,Shadow DOM 样式 由 shell 挂载的自定义元素 共享的设计令牌和浏览器 API 通常可预测,但取决于组件的重量 需要框架灵活性的标准化团队
模块联邦 中等运行时隔离 在运行时加载和挂载远程模块 显式协商或捆绑依赖 当加载和去重是受控的时,效率高 紧密集成的应用程序具有独立的发布
single-spa 边界是指协调而不是完全隔离的模型 通过生命周期钩子注册的应用程序 应用程序和根配置的依赖 依赖于加载规则和框架组合 基于路由的多框架协调

iframes

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

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

Web 组件

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

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

模块联合

模块联合(Module Federation)是Webpack 5引入并由工具如Vite和Rspack支持的功能。它在运行时从远程入口加载编译好的模块。它提供了紧密的集成,使共享组件和协调导航感觉更加自然,而iframe通常做不到。

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

单应用

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

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

利弊和隐患

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

维度 利益 利弊/隐患
团队自主权 团队拥有从头到尾的商业切片 团队必须维护独立的管道、on-call所有权和发布纪律
部署 一个片段可以不重建整个界面而发布 发布变成非原子性,可能会在生产中遇到不兼容的版本
失败隔离 远程失败可以通过回退来隔离 错误边界差可以使导航或关键旅程不可用
性能 懒加载和较小的初始包可以帮助常见流程 更多请求、重复的框架code以及远程初始化可能会损害运行时性能
更多请求、重复的框架 __CAPGO_KEEP_0__ 和远程初始化会损害运行时性能 技术选择 团队可以在允许的边界内使用不同的框架
Security 安全 The shell 可能会执行它尚未充分验证的远程 code
管控 共享标准可以保持产品的一致性 设计系统、依赖规则、合同和平台支持需要持续的协调

性能账单

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

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

安全性

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

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

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

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

测试部署和迁移实践

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

构建层次化的测试系统

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

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

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

微前端测试金字塔的图表,展示孤立的片段测试、合同测试、shell集成和end-to-end旅程。

控制发布面板

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

有用的控制包括:

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

团队应该在一个模拟生产环境中测试 shell 和片段。成功的本地运行并不能证明内容交付路径、缓存、身份验证令牌或远程清单会正确地为用户工作。 部署自动化实践 可以支持可重复的推广和回滚工作流程,但架构仍然需要明确的拥有权。

逐步迁移一个域

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

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

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

在 Capacitor 和 Electron 中使用微前端

A Capacitor 或 Electron 应用程序在浏览器 shell 周围添加了另一个 shell。 Capacitor 将 web code 放置在一个本机 WebView 中,而 Electron 在桌面渲染器进程中运行 web code。 在两种情况下,应用程序都可以加载一个本地 shell,该 shell 可以在运行时从选定的前端 artifact 中获取而不是将每个界面更改嵌入到本机二进制文件中。

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

实时更新和回滚

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

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

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

使用 Capacitor 或 Electron 原生应用壳来实现微前端的示意图

原生壳中的变化

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

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

这个模型加强了回滚,当交付平台提供原子激活和详细的发布指标时。它会使架构更加复杂,当团队假设 web 独立性消除了原生兼容性规划时。原生 shell 仍然是一个合同边界,每个片段都必须尊严它。

选择微前端的时机

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

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

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

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

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

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


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

实时更新Capacitor应用

当网络层面上的bug实时更新时,通过Capgo将修复推送给用户,而不是等待几天的应用商店审批。用户在后台接收更新,而原生变化仍在正常的审批路径中。

最新博客文章

Capgo gives you the best insights you need to create a truly professional mobile app.