05 React架构设计、项目实践与专家清单

本章把前四章的知识汇总到专家能力:控制复杂度、做技术决策、设计演进路径、评审风险,并通过 Knowledge Hub 主线项目贯穿落地。

1. 五层能力模型

层级 能力目标 核心问题
入门 写组件、状态、事件、表单、列表 页面怎么拆?状态怎么更新?
进阶 Hook、副作用、Context、Reducer、异步数据 外部系统怎么同步?复杂状态怎么建模?
高级 渲染机制、性能、Suspense、错误边界 为什么重新渲染?如何定位性能问题?
精通 TypeScript、测试、工程化、组件库、发布 团队如何长期稳定交付?
专家 架构、领域模型、选型、演进、治理 如何控制复杂度和迁移成本?

专家不是知道最多 API,而是能解释取舍。

2. 架构设计目标

架构解决四类复杂度:

  • 业务复杂度:规则、流程、权限、协作。
  • 技术复杂度:性能、数据同步、SSR、跨端。
  • 团队复杂度:多人协作、模块边界、组件复用。
  • 时间复杂度:需求变化、技术债、迁移成本。

3. 分层模型

text 复制代码
app         应用启动、Provider、路由
pages       页面编排、路由参数
features    业务功能模块
entities    领域实体
shared      通用基础能力

依赖方向:

text 复制代码
app -> pages -> features -> entities -> shared

下层不应该依赖上层。

4. Feature-first 目录

text 复制代码
features/knowledge-hub/
├── components/
│   ├── KnowledgeCard.tsx
│   ├── KnowledgeFilters.tsx
│   └── KnowledgeHubView.tsx
├── model/
│   ├── reducer.ts
│   ├── selectors.ts
│   └── types.ts
├── services/
│   └── knowledgeApi.ts
├── hooks/
│   └── useKnowledgeHub.ts
└── index.ts

优点:

  • 同一业务的 UI、状态、服务靠近。
  • 修改需求不需要跨很多目录。
  • 对外暴露稳定入口。

5. 领域模型

业务规则不应散落在 JSX 中。

错误:

jsx 复制代码
{stage.order === 1 || completedStages.includes(stage.order - 1) ? (
  <StartButton />
) : (
  <LockedView />
)}

更好:

ts 复制代码
function canStartStage(progress: Progress, stage: Stage) {
  return stage.order === 1 || progress.completedStages.includes(stage.order - 1);
}

组件:

jsx 复制代码
const unlocked = canStartStage(progress, stage);
return unlocked ? <StartButton /> : <LockedView />;

6. 状态分层

text 复制代码
UI state          弹窗、输入、hover
Page state        当前筛选、分页
Domain state      购物车、学习进度、审批状态
Server state      接口数据、缓存、失效
App state         用户、主题、语言

不要把所有状态塞到一个 store。

7. 服务边界

text 复制代码
component -> hook -> service -> api client

示例:

ts 复制代码
export function useCompleteLesson() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: completeLesson,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['lessons'] });
    },
  });
}

组件只使用业务 Hook:

jsx 复制代码
const completeLesson = useCompleteLesson();

8. Provider 设计

jsx 复制代码
function AppProviders({ children }) {
  return (
    <ThemeProvider>
      <AuthProvider>
        <QueryClientProvider client={queryClient}>
          {children}
        </QueryClientProvider>
      </AuthProvider>
    </ThemeProvider>
  );
}

Provider 适合全局配置,不适合塞所有业务状态。

9. SSR、SSG、CSR 选型

CSR 适合:

  • 登录后后台系统。
  • SEO 不重要。
  • 强交互应用。

SSR 适合:

  • SEO 重要。
  • 首屏体验要求高。
  • 内容依赖请求但需要服务端直出。

SSG 适合:

  • 内容稳定。
  • 文档、博客、营销页。
  • 构建时生成即可。

10. 微前端适用条件

适合:

  • 多团队独立发布。
  • 历史系统渐进迁移。
  • 应用边界清晰。

不适合:

  • 单团队单应用。
  • 只是想拆目录。
  • 共享状态和设计系统还没治理好。

11. ADR 架构决策记录

md 复制代码
# ADR: 使用 TanStack Query 管理服务端状态

## 背景

课程、学习进度、用户信息在多个页面复用,且需要缓存、重试和失效。

## 决策

使用 TanStack Query 管理服务端状态,本地 UI 状态继续使用 useState/useReducer。

## 后果

优点:减少重复请求逻辑,统一 loading/error。
代价:团队需要学习 queryKey 和缓存失效策略。

12. Knowledge Hub 项目背景

团队需要一个内部知识库:

  • 管理 React 学习模块。
  • 支持搜索和层级筛选。
  • 记录收藏和完成状态。
  • 未来接入登录、接口、权限和统计。

当前项目入口:

text 复制代码
src/projects/knowledge-hub/KnowledgeHub.jsx
src/projects/knowledge-hub/knowledgeHubReducer.js

13. Stage 1:静态 UI

目标:把数据变成组件树。

jsx 复制代码
function KnowledgeCard({ item }) {
  return (
    <article>
      <h3>{item.title}</h3>
      <p>{item.summary}</p>
      <TagList tags={item.tags} />
    </article>
  );
}

训练点:

  • JSX。
  • 组件拆分。
  • Props。
  • 列表 key。

14. Stage 2:交互状态

jsx 复制代码
const [query, setQuery] = useState('');
const [level, setLevel] = useState('全部');
const [favorites, setFavorites] = useState([]);

训练点:

  • useState
  • 受控组件。
  • 派生数据。
  • 事件回调。

15. Stage 3:Reducer

jsx 复制代码
const [state, dispatch] = useReducer(reducer, initialState);

dispatch({ type: 'favorite-toggled', id: item.id });

Reducer:

js 复制代码
function reducer(state, action) {
  switch (action.type) {
    case 'favorite-toggled':
      return toggleFavorite(state, action.id);
    case 'completed-toggled':
      return toggleCompleted(state, action.id);
    default:
      return state;
  }
}

训练点:

  • 业务动作。
  • 状态转移。
  • 不可变更新。
  • 可测试逻辑。

16. Stage 4:Selector

js 复制代码
function selectVisibleItems(items, state) {
  return items.filter((item) => {
    const matchLevel = state.level === '全部' || item.level === state.level;
    const matchQuery = item.title.includes(state.query);
    return matchLevel && matchQuery;
  });
}

训练点:

  • 派生数据抽离。
  • 组件变薄。
  • 未来迁移状态库更容易。

17. Stage 5:服务端数据

jsx 复制代码
function KnowledgeHub() {
  const itemsQuery = useKnowledgeItems();
  const progressMutation = useUpdateProgress();

  if (itemsQuery.isLoading) return <Loading />;
  if (itemsQuery.isError) return <ErrorView />;

  return (
    <KnowledgeHubView
      items={itemsQuery.data}
      onComplete={progressMutation.mutate}
    />
  );
}

训练点:

  • 服务端状态。
  • loading/error/empty。
  • mutation。
  • 缓存失效。

18. Stage 6:架构化

text 复制代码
features/knowledge-hub/
├── components/
├── model/
├── services/
├── hooks/
└── index.ts

训练点:

  • 模块边界。
  • 领域模型。
  • 服务层。
  • 对外稳定 API。

19. Stage 7:专家级演进

未来扩展:

  • 接入用户系统:AuthProvider。
  • 接入服务端状态:TanStack Query。
  • 支持路由:课程详情页和学习路径页。
  • 支持权限:管理员编辑、普通用户学习。
  • 支持统计:学习完成率、热门知识点。
  • 支持设计系统:统一按钮、表单、弹窗、表格。
  • 支持测试:Reducer、组件交互、E2E 主流程。
  • 支持 SSR/RSC:内容型页面服务端渲染,交互组件客户端化。

20. React 反模式

直接修改 State:

jsx 复制代码
items.push(newItem);
setItems(items);

派生状态重复存储:

jsx 复制代码
const [total, setTotal] = useState(0);
useEffect(() => setTotal(items.length), [items]);

Effect 滥用:

  • 没有外部系统时通常不需要 Effect。

缺失依赖:

jsx 复制代码
useEffect(() => {
  load(id);
}, []);

数组索引 key:

  • 排序、删除、插入时会出错。

Context 塞所有状态:

  • 渲染范围过大,模块耦合。

到处 useCallback

  • 没有 memo 子组件或依赖稳定需求时收益低。

布尔 Props 爆炸:

jsx 复制代码
<Modal isDelete isAdmin isCompact useNewFooter />

21. 调试顺序

遇到 UI 异常,按顺序排查:

  1. 数据是否正确。
  2. Props 是否传对。
  3. State 是否被直接修改。
  4. key 是否稳定。
  5. Effect 依赖是否完整。
  6. 是否存在竞态请求。
  7. 是否因为 memo 缓存了旧值。

闭包旧值:

jsx 复制代码
useEffect(() => {
  const timer = setInterval(() => {
    setCount(count + 1);
  }, 1000);

  return () => clearInterval(timer);
}, []);

修正:

jsx 复制代码
setCount((current) => current + 1);

22. Code Review 清单

组件:

  • Props 是否表达业务语义?
  • 是否直接修改 State?
  • key 是否稳定?
  • 是否有不必要的状态提升?

Hook:

  • 依赖数组是否完整?
  • Effect 是否真的需要?
  • 清理函数是否存在?
  • 自定义 Hook 是否隐藏复杂副作用?

状态:

  • 派生数据是否重复存储?
  • Reducer action 是否有业务语义?
  • 服务端状态是否误放客户端 store?

性能:

  • 是否有大列表?
  • 是否有昂贵计算?
  • 是否盲目 memo?
  • 是否有包体积风险?

架构:

  • 模块依赖方向是否清晰?
  • 业务规则是否散落在 UI?
  • 公共组件是否过度耦合业务?
  • 是否有迁移和回滚路径?

23. 上线检查

  • build 通过。
  • lint 通过。
  • typecheck 通过。
  • 核心测试通过。
  • 监控接入。
  • 回滚方案明确。
  • 环境变量校验。
  • 包体积可控。
  • 权限由服务端校验。
  • 错误边界覆盖关键区域。

24. 专家判断题

如果能清晰回答这些问题,才接近专家:

  • 为什么这个状态放在这里?
  • 为什么不引入状态库?
  • 为什么这个页面需要或不需要 SSR?
  • 这个组件未来如何扩展?
  • 这个优化如何证明有效?
  • 这个架构决策失败后如何迁移?
  • 当前方案 6 到 18 个月后还能否承载业务变化?

25. 专家思维

专家不会永远选择最复杂方案。专家会问:

  • 当前问题的真实复杂度是什么?
  • 最小可行方案是什么?
  • 哪个决策未来最难迁移?
  • 这个抽象是否真的降低复杂度?
  • 团队是否有能力维护这个方案?

能解释取舍、控制风险、设计演进路径,才是专家能力。

26. 架构场景与演进扩展

后台管理系统:

  • 登录后使用。
  • SEO 不重要。
  • 表格、筛选、表单多。
  • 权限复杂。

推荐 Vite + React Router + TanStack Query;复杂客户端领域状态再引入 Zustand 或 Redux Toolkit;组件库和权限指令要早做治理。

内容站:

  • SEO 重要。
  • 首屏重要。
  • 内容相对稳定。

推荐 Next.js、SSG/SSR、图片优化、CDN 缓存。不要把后台系统的架构套到内容站,也不要把内容站的 SSR 复杂度强加给后台。

高交互编辑器:

  • 本地状态复杂。
  • 操作历史。
  • 快捷键。
  • 大量局部更新。

推荐状态模型先行、Command pattern、undo/redo、局部 store、性能分析,必要时使用 Web Worker。

27. 技术债分类和治理

技术债包括:

  • 认知债:没人知道为什么这样写。
  • 结构债:模块边界混乱。
  • 测试债:关键逻辑无法安全修改。
  • 依赖债:库过期或无人维护。
  • 性能债:没有指标和预算。
  • 设计债:组件和视觉不一致。
  • 发布债:无法快速回滚。

治理方式:

  • ADR。
  • 重构预算。
  • 废弃计划。
  • 自动化检查。
  • 文档和 owner。

28. ADR 模板扩展

md 复制代码
# ADR-0001: 标题

## 状态

Proposed / Accepted / Deprecated / Superseded

## 背景

为什么现在要做决策?

## 备选方案

1. 方案 A
2. 方案 B
3. 方案 C

## 决策

选择哪个方案,为什么?

## 后果

优点、代价、风险、迁移路径。

## 回滚

什么情况下撤销,如何撤销?

29. 专家代码评审模板

text 复制代码
结论:是否可合入?
主要风险:行为、性能、安全、架构、测试。
必须修改:阻塞上线的问题。
建议修改:可后续优化的问题。
验证:已跑哪些测试?缺哪些测试?
后续:是否需要 ADR、监控、清理任务?

30. 专家知识点总表

  • React declarative model。
  • JSX 编译。
  • 组件纯度。
  • Props API。
  • State 快照。
  • 不可变更新。
  • Reducer。
  • Context。
  • Effect 同步。
  • 自定义 Hook。
  • 外部 store。
  • 服务端状态。
  • Suspense。
  • Error Boundary。
  • Concurrent Rendering。
  • SSR。
  • Hydration。
  • RSC。
  • Server Functions。
  • React Compiler。
  • 性能预算。
  • TypeScript 领域建模。
  • 测试金字塔。
  • 设计系统。
  • 权限。
  • 安全。
  • 发布。
  • 监控。
  • ADR。
  • 技术债治理。

31. 架构能力索引

  1. 分层架构。
  2. Feature-first。
  3. 领域模型。
  4. 状态分层。
  5. 服务层。
  6. API DTO 映射。
  7. 权限模型。
  8. 错误边界。
  9. 缓存策略。
  10. 离线策略。
  11. SSR/SSG/CSR 选型。
  12. RSC 边界。
  13. 微前端边界。
  14. 设计系统治理。
  15. 技术债治理。
  16. ADR。
  17. 发布回滚。
  18. 可观测性。
  19. 性能预算。
  20. 团队协作模型。

32. 架构失败信号

  • 新人无法定位业务代码。
  • 修改一个字段牵动十几个文件。
  • 所有东西都依赖 shared。
  • 组件库没人敢升级。
  • 权限判断散落各处。
  • 接口字段直接进入 UI。
  • 状态库里混着服务端数据和 UI 状态。
  • 没有测试保护核心业务。
  • 没有 ADR,没人知道选型原因。
  • 无法快速回滚。

33. 专家决策公式

text 复制代码
决策质量 = 问题匹配度 + 可解释性 + 可迁移性 + 可验证性 - 长期维护成本

做技术决策时,至少写清:

  • 当前问题。
  • 为什么现在解决。
  • 备选方案。
  • 为什么选这个。
  • 失败时如何回退。
  • 未来何时重新评估。

面试题完整答案总集:架构与专家实践

为什么这个状态放在这里?

状态位置由使用范围、业务含义和生命周期决定。只被一个组件使用就放组件内;兄弟组件共享放最近公共父组件;业务流程状态放 feature model;服务端数据放请求缓存;主题、语言、用户放 Provider。状态放得越高,影响范围和耦合越大。

为什么不引入状态库?

如果当前状态只在单页或单 feature 内部协作,useStateuseReducer 和 Context 足够。状态库会引入额外概念、依赖和团队成本。只有出现多页面共享、细粒度订阅、复杂领域状态、DevTools 需求或 Context 性能问题时,引入状态库才更合理。

为什么这个页面需要或不需要 SSR?

需要 SSR 的原因通常是 SEO、首屏性能、内容直出或社交分享。不需要 SSR 的典型场景是登录后后台系统、强交互应用、SEO 不重要、客户端渲染已满足指标。SSR 会增加服务端成本、缓存复杂度和 hydration 问题,所以应基于业务指标决定。

这个组件未来如何扩展?

看组件 API 是否表达稳定语义,内部实现是否可替换,变化点是否被隔离。可扩展组件通常有清晰职责、合理 variant、组合能力和明确废弃策略。不能靠不断增加布尔 Props 扩展,否则状态组合会失控。

这个优化如何证明有效?

必须有优化前后对比指标,例如 Profiler 渲染时间、交互延迟、FPS、包体积、LCP、INP。没有测量的优化只是猜测。优化应写明问题、根因、修改、验证结果和防回退措施。

这个架构决策失败后如何迁移?

专家决策要包含退出方案。例如状态库选错时是否有 selector/hook 适配层,SSR 成本过高时能否回退 CSR,组件库 API 废弃时是否能渐进迁移。没有迁移路径的决策风险很高,应通过 ADR 记录回退条件。

当前方案 6 到 18 个月后还能否承载业务变化?

要从业务增长、团队规模、数据复杂度、性能目标和发布频率评估。如果模块边界清晰、状态分层合理、测试保护关键逻辑、依赖可替换、发布可回滚,就更可能承载变化。若已经出现共享层膨胀、业务规则散落、无测试、无法定位问题,说明需要重构。

什么是专家级前端架构能力?

专家级能力不是使用最复杂技术,而是能识别真实复杂度,选择足够简单的方案,并为未来变化留下迁移路径。它包括领域建模、状态分层、性能预算、工程质量、团队协作、技术债治理和架构决策记录。

相关推荐
人生鹿呀2 小时前
AI 情绪陪伴助手:从 0 到 1 的 PWA + 跨端应用实战
前端
人生鹿呀2 小时前
从零打造滑板文化社区平台:React 19 + Node.js + AI 微服务全栈实战
前端
网络工程小王2 小时前
【LCEL 链式调用详解】调用篇-2
java·服务器·前端·数据库·人工智能
swipe2 小时前
别把语音 Agent 当成“接两个 API”——用 NestJS 搭一套 ASR + LLM + 流式 TTS 的实时语音助手
前端·后端·llm
GISer_Jing3 小时前
AI Agent中游产业链全景拆解:智能体开发的核心生态与技术版图
前端·人工智能·后端
前端之虎陈随易3 小时前
2年没用Nodejs了,Bun很香
linux·前端·javascript·vue.js·typescript
Hooray3 小时前
用时7天,花费30元,我vibe coding这个网站
前端·agent·ai编程
小小高不懂写代码4 小时前
RAG--检索增强生成--原理及实战
前端·人工智能
空中海4 小时前
04 工程化、质量体系与 React 生态
前端·ubuntu·react.js