如何阅读 React 源码呢? 当然是根据代码执行过程阅读更容易理解。本篇文章分享一下利用 VSCode Debugger 阅读源码的简单过程。
闲话少说...上菜
前置搭建
// 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算法。
总结
上述已提到的断点标记有:
scheduleUpdateOnFiberensureRootIsScheduledperformUnitOfWorkreconcileChildren
其中performUnitOfWork,可观察调用栈中上层作用域可以了解workLoopSync还是workLoopConcurrent。
当然很多值得去学习的断点内容。如以下
commitRoot渲染至真实DOM过程逻辑dispatchSetStateuseState Hook中的dispatch如何实现数据响应。