如何阅读 React 源码呢? 当然是根据代码执行过程阅读更容易理解。本篇文章分享一下利用 VSCode Debugger 阅读源码的简单过程。
闲话少说…上菜
前置搭建
// 1. 首先创建一个 react appnpx create-react-app learn-react-app// 2. 切换至 appcd ./learn-react-app// 3. 启动 appnpm run start// 1. 首先创建一个 react app npx create-react-app learn-react-app // 2. 切换至 app cd ./learn-react-app // 3. 启动 app npm run start// 1. 首先创建一个 react app npx create-react-app learn-react-app // 2. 切换至 app cd ./learn-react-app // 3. 启动 app npm run start
启动后,浏览器可以访问本地调试地址 http://localhost:3000
接下来打开 VSCode 打开 learn-react-app 项目,并创建 launch.json
配置 url 本地调试地址
现在我们前置 Debugger 配置部署完毕,运行 Debugger,接下来开始学习阅读 React 源码。
阅读源码
为了更好的学习,建议根据 React技术揭秘 同步理解学习。
本人使用的 React 版本为 18.2.0。
调试技巧:
markXXX
、warnXXX
等非核心逻辑,可使用F10
逐过程跳过或单步跳出- 源码中由
{}
包裹的块级代码也可忽略,这些都是development
环境下的代码片段 - 学习方法多利用左侧观察
变量
的变化、调用栈
向上查找 - 通过 Debugger 过程,找到自己想要学习的代码片段,
标记断点并选择是否启用或禁用
- 一定要多思考理解变量和函数
英文命名
重要的代码片段
ReactDomRoot与FiberRootNode
首先在index.js
标记断点,然后F5
开启 Debugger
F11
单步调试直到进入createRoot
。可以了解到FiberRootNode
、ReactDOMRoot
的创建过程及它们之间的关系。
scheduleUpdateOnFiber
进入root.render()
,深入至scheduleUpdateOnFiber
,并F11
单步调试至内部后标记断点
。
在我们ClassComponent
、FunctionComponent
代码中操作 setState
可以将数据渲染至页面的原因。
ensureRootIsScheduled
继续深入scheduleUpdateOnFiber
并找到ensureRootIsScheduled
,F11
单步调试至内部后标记断点
。
理解该函数的命名
字面意义,确定 FiberRootNode 是否已调度。内部逻辑为获取最高优先级的Lanes
,并决定schedulerCallback
回调执行 performSyncWorkOnRoot
或是performConcurrentWorkOnRoot
,如果是performConcurrentWorkOnRoot
,还会涉及到priority
优先级。
这个方法被调用也会在performConcurrentWorkOnRoot
、performSyncWorkOnRoot
、commitRoot
等有执行。
performUnitOfWork
接下来不具体描述调试步骤。
继续调试至performUnitOfWork
并标记断点
,如果你仔细观察unitOfWork
,它其实就是FiberNode
。而且这里也包含了FiberNode
重要的 render
阶段。
render
阶段如上图所示,包括beginWork
和completeWork
。
reconcileChildren
深入beginWork
可以找到reconcileChildren
并标记断点
,里面reconcileChildFibers
就包含了大家最关心的React diff算法
。
总结
上述已提到的断点标记
有:
scheduleUpdateOnFiber
ensureRootIsScheduled
performUnitOfWork
reconcileChildren
其中performUnitOfWork
,可观察调用栈
中上层作用域
可以了解workLoopSync
还是workLoopConcurrent
。
当然很多值得去学习的断点
内容。如以下
commitRoot
渲染至真实DOM过程逻辑dispatchSetState
useState Hook中的dispatch
如何实现数据响应。