React 微前端架构
React 微前端架构:团队自治与模块联邦的工程实践
引言
当多个团队在同一个 React 应用上并行开发时,单体应用会遭遇「发布节奏互相绑架、代码冲突频繁、技术栈无法演进」等组织问题。微前端把单体拆分为「可独立开发、独立部署、独立演进」的子应用,由主应用(基座)统一编排。本文将从微前端的本质与代价讲起,系统拆解 Module Federation、运行时集成、样式与状态隔离、路由与通信机制,帮助读者理性判断「要不要微前端」。
一、微前端解决什么问题
微前端的核心动机是组织架构而非技术本身:让每个团队拥有完整的「开发-测试-发布」闭环,用技术手段弥合组织边界。
单体与微前端对比
flowchart TB
classDef m1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef m2 fill:#f3e5f5,stroke:#8e24aa,color:#4a148c
classDef m3 fill:#e0f7fa,stroke:#00838f,color:#004d40
subgraph 单体[单体 React 应用]
direction LR
A1[团队 A] --> A2[同一个仓库]
A1 --> A3[同一个发布周期]
A4[团队 B] --> A2
A4 --> A3
A2 --> A5[互相阻塞]
end
subgraph 微前端[微前端架构]
direction LR
B1[主应用基座<br/>导航与编排]
B2[子应用 A<br/>独立仓库/发布]
B3[子应用 B<br/>独立仓库/发布]
B4[子应用 C<br/>独立技术栈]
B1 --> B2
B1 --> B3
B1 --> B4
end
click B1 "https://micro-frontends.org/" "微前端官方文档"
class 单体 m2
class A1 m2
class A2 m2
class A3 m2
class A4 m2
class A5 m2
class 微前端 m1
class B1 m3
class B2 m3
class B3 m3
class B4 m3
微前端的代价
| 维度 | 收益 | 代价 |
|---|---|---|
| 团队自治 | 独立发布迭代 | 集成测试复杂化 |
| 技术演进 | 子应用可换技术栈 | 重复依赖 体积上升 |
| 部署 | 独立滚动发布 | 版本兼容管理 |
| 体验 | — | 首屏多次加载风险 |
核心判断:微前端的收益随「团队数量」增长,代价随「应用交互复杂度」增长。两三个团队以内,单体 + 模块化通常是更优解。
二、运行时集成:三种主流方案
微前端的集成方式决定「子应用如何被加载」:路由分发、iframe 隔离、模块联邦。
方案对比
flowchart LR
classDef s1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef s2 fill:#f3e5f5,stroke:#8e24aa,color:#4a148c
classDef s3 fill:#e0f7fa,stroke:#00838f,color:#004d40
A[运行时集成方案] --> B[iframe<br/>最强隔离]
A --> C[JS Entry<br/>动态脚本加载]
A --> D[Module Federation<br/>模块级共享]
B --> B1[独立 DOM/JS/CSS 环境]
B --> B2[通信成本高 体验割裂]
C --> C1[灵活可控]
C --> C2[需自建沙箱]
D --> D1[依赖共享 体积优化]
D --> D2[构建期契约]
click D "https://webpack.js.org/concepts/module-federation/" "Module Federation 文档"
class A s1
class B s2
class C s2
class D s2
class B1 s3
class B2 s3
class C1 s3
class C2 s3
class D1 s3
class D2 s3
Module Federation 的核心模型
Module Federation 让多个构建产物在运行时互相消费模块——主应用声明 remote,子应用声明 expose,公共依赖(如 React)声明 shared 只加载一次。
flowchart TB
classDef f1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef f2 fill:#f3e5f5,stroke:#8e24aa,color:#4a148c
classDef f3 fill:#e0f7fa,stroke:#00838f,color:#004d40
A[主应用 host] --> B[shared: react/react-dom<br/>全局单例]
A --> C[remote 声明]
C --> D[子应用 A 远程模块]
C --> E[子应用 B 远程模块]
D --> F[子应用共享主应用的 React]
E --> F
click B "https://webpack.js.org/plugins/module-federation-plugin/" "MF 插件文档"
class A f1
class B f2
class C f1
class D f2
class E f2
class F f3
三、主应用基座的设计
基座(Shell)负责导航、路由编排与子应用生命周期管理——微前端的「骨架」。
基座架构
flowchart TB
classDef b1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef b2 fill:#f3e5f5,stroke:#8e24aa,color:#4a148c
classDef b3 fill:#e0f7fa,stroke:#00838f,color:#004d40
A[主应用基座] --> B[全局导航与布局]
A --> C[路由注册表<br/>子应用路由映射]
A --> D[子应用生命周期<br/>加载/挂载/卸载]
A --> E[全局状态与事件总线]
B --> F[统一品牌体验]
C --> G[URL 路由分发]
D --> H[动态加载卸载]
E --> I[跨应用通信]
click C "https://qiankun.umijs.org/zh/guide" "qiankun 文档"
class A b1
class B b1
class C b2
class D b2
class E b2
class F b3
class G b3
class H b3
class I b3
子应用生命周期
stateDiagram-v2
direction LR
[*] --> Loading: 路由匹配
Loading --> Mounted: 脚本加载完成
Mounted --> Unmounting: 离开路由
Unmounting --> Mounted: 重新进入
Unmounting --> [*]: 完全卸载
note right of Mounted
子应用接管容器 DOM
注册自己的路由与事件
end note
四、样式与状态隔离
微前端的两个关键隔离问题:CSS 隔离与JavaScript 状态隔离。
隔离策略
flowchart TD
classDef g1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef g2 fill:#f3e5f5,stroke:#8e24aa,color:#4a148c
classDef g3 fill:#e0f7fa,stroke:#00838f,color:#004d40
A[隔离需求] --> B[CSS 隔离]
A --> C[JS 状态隔离]
B --> D{方案}
D -->|样式前缀| E[BEM / CSS Modules]
D -->|运行时沙箱| F[CSS-in-JS 或 iframe]
C --> G{方案}
G -->|单例模式| H[window 共享 易冲突]
G -->|代理沙箱| I[Proxy 隔离读写]
click F "https://qiankun.umijs.org/zh/guide/css" "qiankun 样式隔离"
class A g1
class B g1
class C g1
class D g2
class E g3
class F g3
class G g2
class H g3
class I g3
样式隔离对比
| 方案 | 隔离强度 | 实现成本 | 适用场景 |
|---|---|---|---|
| BEM/CSS Modules | 约定级 | 低 | 团队规范强 |
| CSS-in-JS | 运行时级 | 中 | 新项目 |
| 动态样式包裹 | 加载级 | 中 | qiankun 等框架 |
| iframe | 物理级 | 高 | 强隔离需求 |
五、路由与通信机制
微前端的路由需要「主应用路由 → 子应用路由」的映射协作;跨应用通信则依赖共享事件总线或全局状态。
路由协作模型
sequenceDiagram
participant U as 用户
participant M as 主应用
participant S as 子应用
U->>M: 访问 /app-b/posts/123
M->>M: 路由注册表匹配子应用 B
M->>S: 加载并挂载子应用
S->>S: 接管子路由 /posts/123
S->>M: 内部跳转更新 URL
M->>M: 基座导航状态同步
Note over M,S: URL 是唯一事实来源
通信机制对比
flowchart LR
classDef c1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef c2 fill:#f3e5f5,stroke:#8e24aa,color:#4a148c
classDef c3 fill:#e0f7fa,stroke:#00838f,color:#004d40
A[跨应用通信] --> B[URL 参数<br/>只读状态 可分享]
A --> C[全局事件<br/>CustomEvent 发布订阅]
A --> D[共享状态库<br/>全局 store]
A --> E[回调用途<br/>基座注入]
click C "https://developer.mozilla.org/zh-CN/docs/Web/API/CustomEvent" "CustomEvent 文档"
class A c1
class B c2
class C c2
class D c2
class E c2
class F c3
推荐:默认用 URL 传参(可分享、可回退);需要实时通知用全局事件总线;高频共享状态谨慎使用全局 store(耦合度最高)。
六、公共依赖与体积治理
Module Federation 的 shared 配置让 React 等公共依赖只加载一次,但配置不当会导致版本冲突与重复加载。
依赖共享决策
flowchart TD
classDef d1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef d2 fill:#fff3e0,stroke:#f57c00,color:#e65100
classDef d3 fill:#e8f5e9,stroke:#388e3c,color:#1b5e20
A[公共依赖共享] --> B{依赖类型}
B -->|框架层 react/react-dom| C[必须共享<br/>单例渲染]
B -->|状态库| D{版本一致}
D -->|是| E[共享 节省体积]
D -->|否| F[各自携带 隔离]
B -->|业务库| G{体积与冲突}
G -->|大且稳定| H[共享]
G -->|易变| I[不共享]
click C "https://webpack.js.org/plugins/module-federation-plugin/#sharing-libraries" "共享库文档"
class A d1
class B d1
class C d3
class D d2
class E d3
class F d3
class G d2
class H d3
class I d3
七、微前端的适用性判断
微前端不是银弹——它解决组织问题,也引入新的工程复杂度。
决策流程
flowchart TD
classDef y1 fill:#e3f2fd,stroke:#1976d2,color:#0d47a1
classDef y2 fill:#fff3e0,stroke:#f57c00,color:#e65100
classDef y3 fill:#e8f5e9,stroke:#388e3c,color:#1b5e20
A[是否需要微前端] --> B{团队数量与耦合}
B -->|单一团队| C{应用规模}
C -->|中小| D[单体 + 模块化]
C -->|超大| E[考虑拆包优化 勿上微前端]
B -->|多团队| F{发布节奏}
F -->|同步发布可行| G[单体多包]
F -->|必须独立发布| H{集成复杂度}
H -->|低| I[Module Federation]
H -->|高| J[iframe 或重评估]
click I "https://micro-frontends.org/" "微前端文档"
class A y1
class B y1
class C y2
class D y3
class E y3
class F y2
class G y3
class H y2
class I y3
class J y3
八、总结
微前端的本质是「用技术手段解决组织边界」:
- 动机:团队自治、独立发布、技术演进;
- 方案:iframe 强隔离、JS Entry 灵活、Module Federation 共享;
- 基座:路由编排 + 生命周期管理 + 通信总线;
- 隔离:CSS 前缀约定 + JS 沙箱代理;
- 通信:URL 优先、事件其次、共享 store 慎用;
- 判断:多团队 + 独立发布是前提,否则别上微前端。
实践建议:从「单体 + 代码模块化」起步,先在打包层(分包/联邦)解决问题;只有组织层面确实需要独立发布闭环时,才升级到完整微前端。下一篇我们将探讨 React 国际化 i18n 的完整方案。
