如何有效地阅读 React 源码
1. 阅读前的准备
关于行号引用:本仓库所有文档中的源码行号(如
ReactFiberHooks.js:1948)对应 2026 年 8 月 React 官方仓库main分支快照(ReactVersion =19.3.0开发版)。随着 React 主分支持续推进 commit,行号可能逐渐偏移——建议以函数名而非行号为搜索锚点,行号仅用于辅助定位。
1.1 环境准备
bash
# 克隆源码
git clone https://github.com/facebook/react.git
cd react
# 安装依赖
yarn install
# 构建(可选,用于调试)
yarn build1.2 推荐工具
- VS Code:配合 Flow 类型检查扩展
- Chrome DevTools:断点调试
- React DevTools:观察组件树和 Profiler
- CodeTour(VS Code 扩展):源码路径标注
2. 阅读策略
2.1 不要从头到尾读
React 源码有数万行,线性阅读会迷失。带着问题找答案是更有效的方式:
错误方式:
从 ReactFiberWorkLoop.js 第一行开始读 → 迷失在数千行代码中
正确方式:
问题:「setState 后 React 做了什么?」
→ 从 ReactBaseClasses.js 的 setState → updater.enqueueSetState
→ ReactFiberConcurrentUpdates.js → scheduleUpdateOnFiber
→ ReactFiberRootScheduler.js → ensureRootIsScheduled
→ scheduler/Scheduler.js → scheduleCallback
→ 回到 ReactFiberWorkLoop.js 的 performConcurrentWorkOnRoot
→ workLoopConcurrentByScheduler → performUnitOfWork → beginWork → completeWork → commit
只读这条链路上的关键函数,忽略旁支。2.2 从入口跟踪调用链
使用 VS Code 的"Go to Definition"和"Find All References"跟踪调用链:
setState 怎么触发渲染?
1. ReactBaseClasses.js: this.setState → this.updater.enqueueSetState
2. ReactFiberClassComponent.js: enqueueSetState → 创建 Update
3. ReactFiberConcurrentUpdates.js: enqueueUpdate → 加入队列
4. ReactFiberWorkLoop.js: scheduleUpdateOnFiber(root, fiber, lane) → markRootUpdated (ReactFiberLane.js)
5. ReactFiberRootScheduler.js: ensureRootIsScheduled → scheduleCallback
6. Scheduler.js: push(taskQueue, task) → requestHostCallback
7. MessageChannel → flushWork → performConcurrentWorkOnRoot
8. ReactFiberWorkLoop.js: renderRootConcurrent → workLoopConcurrentByScheduler
9. performUnitOfWork → beginWork → completeWork
10. commitRoot → commitMutationEffects → DOM 更新2.3 用断点辅助理解
在 Chrome 中调试 React 源码:
- 用
fixtures/concurrent/下的 demo 应用 yarn build构建开发版本- 在 Chrome DevTools 中打开 Source 面板
- 在关键函数设断点(如
performUnitOfWork、beginWork) - 触发更新(点击按钮),观察调用栈
2.4 关注注释
React 源码的注释质量很高,很多关键设计都有详细说明:
javascript
// ReactFiber.js:326-330
// We use a double buffering pooling technique because we know that we'll
// only ever need at most two versions of a tree. We pool the "other" unused
// node that we're free to reuse. This is lazily created to avoid allocating
// extra objects for things that are never updated.2.5 关注 Feature Flags
React 源码中大量使用 Feature Flags 控制行为:
javascript
if (enableProfilerTimer) { ... }
if (enableViewTransition) { ... }
if (disableLegacyMode) { ... }阅读时忽略被 flag 关闭的分支,只关注核心路径。
3. 推荐阅读顺序
阶段 1(建立全局认知):
→ 00-overview 三篇文档
→ ReactFiberWorkLoop.js 的 workLoop 和 performUnitOfWork
→ 理解"递归"和"归"的整体流程
阶段 2(深入数据结构):
→ ReactInternalTypes.js(Fiber 和 FiberRoot 的类型定义)
→ ReactWorkTags.js(了解所有组件类型)
→ ReactFiberFlags.js(了解所有副作用标记)
→ ReactFiberLane.js(了解优先级模型)
阶段 3(理解渲染流程):
→ ReactFiberBeginWork.js(beginWork 的 switch 分支)
→ ReactChildFiber.js(Diff 算法)
→ ReactFiberCompleteWork.js(DOM 创建)
→ ReactFiberCommitWork.js(DOM 更新)
阶段 4(理解 Hooks):
→ ReactFiberHooks.js(先读 mountState/updateState)
→ 理解 hooks 链表的工作方式
阶段 5(理解调度):
→ scheduler/Scheduler.js
→ SchedulerMinHeap.js
阶段 6(进阶):
→ ReactFiberThrow.js(错误处理)
→ ReactFiberSuspenseComponent.js(Suspense)
→ RSC 相关源码4. 实践检验
每读完一个主题,用以下方式检验理解:
- 能画出流程图吗? 在纸上画出该主题的数据流/控制流
- 能解释给同事听吗? 用自己的语言叙述核心机制
- 能做对应的实践练习吗? 完成
practices/中的对应练习 - 能在源码中找到答案吗? 遇到实际问题时能定位到源码
5. 常见误区
误区 1:「我需要理解每一行代码」
→ 不需要。先理解 20% 的核心代码,它们覆盖了 80% 的行为。
误区 2:「源码必须在线读」
→ 本地 clone 后用 VS Code 更好:可以搜索、跳转、断点。
误区 3:「从 v15 开始读更容易」
→ 不推荐。v15 的 Stack Reconciler 与现代 React 差异太大。
直接读 Fiber 架构的代码,对照本仓库的文档理解。
误区 4:「先读完所有源码再写代码」
→ 交替进行更好。读源码 → 写实践代码 → 再读源码 → 再写代码。
实践是检验理解的唯一方式。下一步
- 手写 mini-react — 从零实现 React 核心
- 源码阅读实战 — 源码阅读实战
- 术语表 — 核心术语速查
参考资料
- React 技术揭秘 - 调试源码 (卡颂) — 源码调试方法
- How to read React source code (Reddit) — 社区源码阅读经验分享
- React Contributing Guide — 官方贡献指南