
引言:架构师的"身后事"
- 痛点直击:你是否遇到过这种情况?新项目启动时写了几十页 文档 (打个比方) ,三个月后代码改得面目全非,文档却再也没人打开过。
- 核心冲突 :代码是写给机器看的(追求准确),文档是写给未来的团队看的(追求理解)。
- 观点抛出:一份好的架构文档(ADD - Architecture Design Document)不是繁文缛节,它是团队协作的"契约"和技术决策的"黑匣子"。
1. 法则一:升维思考 ------ 引入 C4 模型
上一篇我们讲了 UML(微观的画笔),这一篇我们要讲宏观的地图。
-
为什么要引入 C4?
- 传统的 4+1 视图对敏捷开发来说有时过于厚重。
- C4 模型 (Context, Containers, Components, Code) 像 Google Maps 一样,提供了从"全球"到"街道"的 4 个缩放级别,更适合现代 Web 应用。
-
前端视角的 C4 拆解(图文结合):
- Level 1: System Context (系统上下文) :
- 画什么:你的 Web App 和外部系统(支付网关、老后端、CDN)的关系。
- 给谁看:非技术人员、产品经理。
graph TD A[电商前端] -->|HTTPS| B[支付网关] A -->|WebSocket| C[实时推荐服务] D[老后端] -->|REST| A E[CDN] -->|静态资源| A-
Level 2: Containers (容器) :
- 画什么 :这是前端架构师的主战场。SPA 客户端、BFF 层 (Node.js)、微前端子应用、移动端 WebView。
- 给谁看:开发团队、运维。
graph TB subgraph 前端架构 A[SPA客户端] -->|GraphQL| B[BFF层] B -->|RPC| C[微前端子应用] D[移动端WebView] -->|REST| B end-
Level 3: Components (组件) :
- 画什么 :不是 React UI 组件,是业务功能模块(如:购物车控制器、身份认证服务、日志模块)。
graph LR A[购物车控制器] -->|事件总线| B[库存校验服务] A -->|LocalStorage| C[本地缓存] D[身份认证模块] -->|JWT| E[API网关]-
Level 4: Code (代码) :
- 观点 :不要画! 代码变化太快,图通过 IDE 自动生成即可,画了必死。
2. 法则二:决策留痕 ------ 架构决策记录 (ADR)
这是本文最"硬核"、最能体现架构师价值的部分。
-
什么是 ADR?
- 文档不仅要记录"由于什么(Result)",更要记录"为什么(Why)"。
- 很多时候,新同事骂代码烂,是因为他们不知道当年的约束条件。
-
ADR 标准模板(直接给干货):
-
标题:ADR-001 采用 Tailwind CSS 替代 Styled-components
-
状态:已通过 / 已废弃 / 提议中
-
背景 (Context) :现有 CSS-in-JS 方案导致 Bundle 体积过大,且团队命名困难。
-
决策 (Decision) :全线引入 Tailwind CSS。
-
后果 (Consequences) :
- (+) 这里的 HTML 会变丑。
- (+) 样式文件体积减少 40%。
- (-) 需要统一配置 ESLint 插件进行类名排序。
-
-
建议:
- 不要把 ADR 写在 Word 里,要放在代码仓库的
/docs/adr目录下。
- 不要把 ADR 写在 Word 里,要放在代码仓库的
3. 法则三:文档即代码 (Docs as Code)
如何保证文档"活着"?让它和代码住在一起。
-
工具链推荐:
- 存储 :Git 仓库(与
package.json同级)。 - 编写:Markdown。
- 画图:Mermaid(直接在 Markdown 里写代码生成图,便于 Git Diff 对比修改)。
- 发布:VitePress / Docusaurus(自动构建成静态站点)。
- 存储 :Git 仓库(与
-
目录结构示例:
4. 落地模板:一份"不被嫌弃"的架构文档骨架
-
背景与目标 (1句话说明项目价值)
- [痛点/现状] + [解决方案] + [量化价值]
- 示例 : "打造企业级前端微服务基座,通过微前端架构解耦巨石应用,实现多团队独立部署,并统一全线产品的 UI 交互体验与鉴权逻辑。"

-
约束条件 (必须兼容 IE?必须 2 周上线?)
- 根据内部自定义
-
系统架构图 (示例)
graph LR %% 重构类项目 P1["老旧系统"] --> S1["技术升级
React 18 + Vite"] --> V1["性能提升
维护成本降低"] %% 高并发项目 P2["CSR瓶颈"] --> S2["SSR渲染
CDN分发"] --> V2["SEO优化
转化率提升"] %% 中台项目 P3["巨石应用"] --> S3["微前端
模块解耦"] --> V3["独立部署
团队协作优化"] %% 样式 classDef pStyle fill:#ffebee,stroke:#f44336,color:#b71c1c classDef sStyle fill:#e3f2fd,stroke:#2196f3,color:#0d47a1 classDef vStyle fill:#e8f5e9,stroke:#4caf50,color:#1b5e20 class P1,P2,P3 pStyle class S1,S2,S3 sStyle class V1,V2,V3 vStyle -
关键技术选型 (链接到具体的 ADR 文件)
graph LR %% 技术分类 框架选型 --> React 构建工具 --> Vite 渲染模式 --> NextJS 架构方案 --> Qiankun %% 具体技术 React["React 18"] --> ADR1[" ADR-001"] Vite["Vite 5.x"] --> ADR2["ADR-002"] NextJS[" Next.js SSR"] --> ADR3[" ADR-003"] Qiankun[" qiankun"] --> ADR4[" ADR-004"] %% 替代说明 React -.->|替代 jQuery| Legacy1 Vite -.->|替代 Webpack| Legacy2 NextJS -.->|优化首屏| Target1["FCP < 1.5s"] Qiankun -.->|微前端基座| Target2["模块解耦"] %% 样式 classDef cat fill:#f5f5f5,stroke:#616161,font-weight:bold classDef tech fill:#bbdefb,stroke:#1976d2,color:#0d47a1 classDef adr fill:#c8e6c9,stroke:#388e3c,color:#1b5e20 class 框架选型,构建工具,渲染模式,架构方案 cat class React,Vite,NextJS,Qiankun tech class ADR1,ADR2,ADR3,ADR4 adr -
非功能性需求 (NFRs)
- 性能:FCP < 1.5s
- 安全:XSS 防护策略
- 监控:Sentry 报警规则
graph LR %% 根节点 NFRs["非功能性需求"] --> Perf NFRs --> Sec NFRs --> Mon %% 性能需求 Perf["性能需求
Performance"] --> P1["首屏<1.5s"] Perf --> P2["交互<100ms"] Perf --> P3["资源优化"] %% 安全需求 Sec["安全需求
Security"] --> S1["XSS防护"] Sec --> S2["CSRF防护"] Sec --> S3["数据加密"] %% 监控需求 Mon["监控需求
Monitoring"] --> M1["错误率<0.1%"] Mon --> M2["性能告警"] Mon --> M3["用户追踪"] %% 样式 classDef rootStyle fill:#34495e,stroke:#2c3e50,color:white,font-size:16px classDef perfStyle fill:#3498db,stroke:#2980b9,color:white classDef secStyle fill:#e74c3c,stroke:#c0392b,color:white classDef monStyle fill:#2ecc71,stroke:#27ae60,color:white class NFRs rootStyle class Perf,P1,P2,P3 perfStyle class Sec,S1,S2,S3 secStyle class Mon,M1,M2,M3 monStyle
概括总结
"架构师的产出不是文档,而是共识。"
好的架构文档,不是为了证明你通过了答辩,而是为了让新入职的同学在一年后看到这行代码时,能通过文档里的 ADR 明白: "哦,原来当初是为了性能才写得这么'奇怪'的。"
这就是文档的价值------穿越时间的沟通。