这周,我将开始对React的源码深入的学习,并在这里做一个简单的记录📝与分享。
本地调试源码
1、从facebook/react 项目拉取最新的源码 2、基于最新的源码构建react、react-dom 3、创建独立的HTML文件,通过script标签加载本地的UMD文件。
# 克隆
git clone https://github.com/facebook/react.git
# 安装依赖
cd react & yarn
# 构建
yarn build react/index,react-dom/index --type=UMD
⚠️:
当我们尝试以UMD的格式构建react和react-dom的时候,发现在build文件里并没有出现我们想要的UMD格式的文件, 查看打包文件:发现并没有UMD的打包类型,原来构建umd产物的代码已经被删掉啦:
为了快速调试,我直接将代码回退到删除umd的版本:
git checkout -b debug-react 0c245df
尝试构建,正常输出
宏观结构
- react
基础包,只提供定义React 组件(ReactElement)的必要函数,可以理解为一个api的库
- react-dom
react的渲染器,将react-reconciler中的运行结果输出到web界面,大多数场景下,能用到此包的就是一个入口函数,ReactDOM.render(<App/>,ducument.getElementById('root')),其他的都是react中的api
- react-reconciler
枢纽,综合协调react、react-dom、scheduler各包之间的调用和配合,管理react应用状态的输入和结果的输出,将结果传递给渲染器
- scheduler
调度机制的核心实现,控制由react-reconciler提供的回调函数的执行时机。
两大工作循环
1、任务调度循环
位于scheduler,需要循环调用,控制所有task的调用
2、fiber构造循环
位于react-reconciler,控制fiber树的构成,整个过程是一个深度优先遍历
主干逻辑:
大循环(任务调度循环)负责调度task,小循环(fiber构造循环)负责实现task
-
输入:每一次的更新(新增、删除、修改节点)视为一次更新需求(目的是更新DOM节点)
-
注册调度任务:react-reconciler收到更新需求的时候,并不会立即构造fiber树,而是去调度中心scheduler中注册一个新任务task,即把更新续期转换为一个task
-
执行调度任务(输出):scheduler通过任务调度循环来执行task,task的执行过程又回到啦react-reconciler包中
- fiber循环结构是task实现的第一步,循环完成之后会构造出新的fiber树
- commitRoot是task实现的第二步,把最新的fiber树最终渲染到页面上,task完成