一致性不是一个可以达到的目标,而是一项你需要支付的订阅费用。每个工程组织最终都会发现这一点,通常是在第二个或第三个团队开始向同一个仓库提交代码的时候。无论你运行的是单个 React 单体应用,还是由一系列可独立部署的前端组成的星群,你都无法实现零成本优化。你只是在选择每个季度哪张账单会出现在面前。

单体架构的协调税

在单体架构中,账单是以人力工时来体现的。团队每天都要花时间在共享代码、样式和发布计划上达成一致。一个想要发布微小结账修复功能的开发人员,可能需要升级被其他六七个团队使用的共享依赖,然后等待完整的回归测试套件通过。这种成本在悄无声息地累积。它从未出现在云账单的明细项中,而是隐藏在降低的开发速率中,隐藏在工程师在关于代码风格的 Slack 讨论中频繁切换上下文的过程中,也隐藏在那种无人负责但人人都会触碰的 CSS 架构所带来的缓慢摩擦中。

随着团队的增长,这种税收也会随之增加。代码审查的瓶颈会从技术问题转向社交问题。一个拥有两百名贡献者的单一仓库并不会线性扩展;它是呈组合式增长的。合并队列会发生积压。发布周期会拉长到数天。设计系统变成了一个政治实体,需要一个管理委员会来批准一个新的按钮变体。单体架构并非出于恶意而抵制变革。它抵制变革是因为每一个表面都是共享的,每一次变更都需要达成共识。

划定边界

微前端将协调成本转移到了特定的边界内。你不再需要每周开会讨论共享状态管理,而是划定一条线。团队 A 负责产品目录,团队 B 负责购物车。它们就一个契约达成一致(通常是一个路由边界或一个精简的事件 Schema),然后便不再交谈。这是核心的权衡:用一种不同形式的纪律来换取自主权。

理论上很简洁。如果 Shipping 团队重构了其路由层,Billing 团队不应该受到影响。如果搜索界面需要每天部署五次,它不应该等待账户设置页完成其端到端测试。边界将组织摩擦转化为了技术接口。但划定这条线从来都不是免费的。

基础设施账单

微前端会产生平台成本。你需要一个能够运行时组合各个片段的 Shell 应用。你需要一个能够理解如何将多个构建作业的产物组装成单个连贯页面的部署流水线。如果你使用的是 Webpack Module Federation,你现在需要管理跨独立构建包的共享依赖版本。如果你使用的是 iframe,你正在调试跨域消息并与布局偏移作斗争。如果你使用的是 Web Components,你正在分布式图中管理自定义元素的版本,其中一个团队的升级可能会遮蔽另一个团队的升级。

这些成本是具体且持续发生的。你为构建编排付费,以确保在发布六个前端应用时不会破坏第七个。你为可观测性付费,以便跨越三个由三个不同团队拥有的独立 JavaScript 包来追踪用户行为。你为性能治理付费,因为如果六个团队都打包各自的工具库副本,除非有人构建并维护一套去重策略,否则你的页面会变成一个沉重的负担。到那时,你实际上重新创造了你试图逃离的单体架构的一部分,只不过现在它需要一个平台团队来维护。

当成本发生转移时

想象一家拥有四个前端团队、共享同一个 Next.js 应用的中型 SaaS 公司。在经过三小时的 CI 运行后,每天会进行两次部署。当 Shipping 团队想要重构导航栏时,他们会提交评论请求,更新整个树状结构中的导入路径,然后等待两周让 Billing 团队调整其集成测试。成本就是协调,简单直接。

他们拆分为微前端。每个团队现在负责一个垂直领域,并按照自己的进度推送到生产环境。第一个月感觉像是获得了自由。然后,一个 Bug 出现了。全局页眉在 Safari 中无法渲染,因为 Shipping 团队升级了一个 CSS-in-JS 库,该库与 Search 团队注入的基础样式发生了冲突。调试需要三名值班工程师、一个共享的作战室,以及对两个服务进行痛苦的回滚,因为 Shell 应用缓存了模块清单。成本转移了,但并未消失。

规模化的算术

两种模式都不是免费的。一个 15 人的初创公司不需要平台团队。模块联邦(module federation)、独立部署流水线和分布式契约测试带来的开销会吞噬掉他们所有的开发速度。他们应该通过协作来支付成本,因为协作的成本很低。他们可以在十分钟的交谈中就达成状态管理模式的共识,并在当天下午就将其发布。

一个拥有数十个业务单元、且各单元运行在不同季度周期下的五百人规模的企业则面临着相反的问题。协作税已呈指数级增长。发布周期(Release trains)需要数周时间。平台工程的人力成本已是预算中的既定事实,因此增加微前端基础设施只是边际成本,而不是一项新的开支。对他们而言,用部署图来取代对齐会议是一种理性的权衡。

真正的问题在于,哪种“账单”更适合你团队的规模。单体架构在人类协作的极限处向你征税;而微前端则在平台工程的基础层向你征税。

选择你的“货币”

如果你选择微前端,请明确你购买的是什么。你购买的是团队的自主权和独立的可部署性。请做好为以下内容买单的准备:

  • 一个处理片段(fragments)之间组合、路由和错误边界的运行时外壳(runtime shell)。
  • 一项侧重于去重策略而非共享实现逻辑的共享依赖策略。
  • 针对每个集成面的跨团队契约测试。
  • 能够关联分布式包(bundles)中用户点击行为的统一可观测性。
  • 一套性能治理模型,因为没有哪个团队能单独掌控浏览器下载的最终有效载荷(payload)。

如果你选择单体架构,请诚实面对账单。你是在用同步来换取简单。你需要为以下内容付费:

  • 共享代码所有权,以及保持其一致性所需的治理规范。
  • 由流水线中最慢的集成测试所决定的发布节奏。
  • 库升级时带来的广泛影响范围(blast radius)。
  • 一个逐渐显现的现实:你最快的工程师将不得不按照最谨慎的工程师的速度来行动。

核心启示

没有哪种架构可以免除成本。有的只是货币的选择。聪明的组织不再寻找“免费”的选项,而是开始评估自己究竟能承担哪种成本。你必须决定,你是想通过人力协作来支付,还是通过平台开销来支付。无论哪种情况,保持统一性都是一种持续的支出。唯一的问题是,由谁来买单。