- 文档
- 前端
【免费下载链接】just-react
「React技术揭秘」 一本自顶向下的React源码分析书
导读
本文是「React技术揭秘」源码分析系列中的关键一环:在了解了 React 16 的Scheduler(调度器)— Reconciler(协调器)— Renderer(渲染器)三层架构之后,我们需要知道这套架构是如何落到源码的文件结构上的。读完本文,你将掌握react仓库根目录与packages目录的完整组织方式,能够准确区分核心包、Renderer 包、试验性包与辅助包,并理解react-reconciler为什么是源码学习中 80% 代码量的来源。
背景:三层架构如何映射到源码
在 React 16 中,架构被重构为三层,这也是理解文件结构的先决条件(详见 docs/preparation/newConstructure.md):
- Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入 Reconciler
- Reconciler(协调器)—— 负责找出变化的组件
- Renderer(渲染器)—— 负责将变化的组件渲染到页面上
与 React 15 相比,React 16 新增了 Scheduler 这一层。它的出现是为了解决同步更新无法支持可中断的异步更新的问题——当浏览器帧内没有剩余时间时,需要一种机制通知 React 暂停工作(详见 docs/preparation/idea.md)。Scheduler 正是 React 实现的requestIdleCallbackpolyfill,其工作方式(时间切片与优先级调度)详见 docs/concurrent/scheduler.md。
那么,这套三层架构是如何体现在源码的文件结构上的呢?答案就在react仓库的顶层目录与packages目录中。
顶层目录
除去配置文件和隐藏文件夹,react仓库根目录下包含三个核心文件夹:
根目录 ├── fixtures # 包含一些给贡献者准备的小型 React 测试项目 ├── packages # 包含元数据(比如 package.json)和 React 仓库中所有 package 的源码(子目录 src) ├── scripts # 各种工具链的脚本,比如git、jest、eslint等三个目录分工明确:
- fixtures:面向贡献者的测试项目集合,用于在接近真实应用的场景中验证 React 行为;
- packages:整个仓库的核心,所有 package 的源码(
src子目录)与元数据(package.json)都集中在这里,本系列文章的主要研究对象; - scripts:工具链脚本,涵盖 git 钩子、jest 测试、eslint 检查、构建等自动化流程。
补充:在当前仓库(just-react)的 package.json 中可以看到,这是一本基于 VuePress 构建的源码分析书,
npm run start会以vuepress dev docs启动本地阅读环境,npm run build用于构建静态站点。这与 React 官方仓库中packages/scripts承载构建/测试工具链的定位是一致的。
packages 目录
packages目录下的文件夹非常多,按职责可划分为四大类:核心包、Renderer 相关包、试验性包与辅助包。下面逐一展开。
react 文件夹:全局 API 的核心
react是 React 的核心,包含所有全局 React API,例如:
React.createElementReact.ComponentReact.Children
这些 API 是全平台通用的,它不包含ReactDOM、ReactNative等平台特定的代码。在 NPM 上作为单独的一个包(react)发布。
理解要点:
react包只定义“组件是什么”与“如何描述 UI”,不关心“如何把 UI 渲染到哪个宿主环境”。平台相关的渲染逻辑被拆到了各自的 Renderer 包中,这正是 React 跨平台能力的根基。
scheduler 文件夹:调度器的实现
Scheduler(调度器)的实现就位于packages/scheduler。
从源码结构看,Scheduler 是独立于 React 的库,其职责包含两点:
- 时间切片:基于宏任务(优先
MessageChannel,不支持时回退setTimeout)模拟requestIdleCallback,为每个任务分配初始5ms的剩余时间; - 优先级调度:对外暴露
unstable_runWithPriority、unstable_scheduleCallback等 API,按五种优先级(ImmediatePriority、UserBlockingPriority、NormalPriority、LowPriority、IdlePriority)对应的过期时间(-1、250ms、5000ms、10000ms、永不超时)对任务排序执行。
关于 Scheduler 内部机制,在 docs/concurrent/scheduler.md 中有完整的源码级讲解,这里只需记住:它是独立于 React 的一套优先级体系,与 React 内部的 lane 优先级模型相互映射。
shared 文件夹:公共方法与全局变量
shared中保存了源码中其他模块公用的方法和全局变量。例如在shared/ReactSymbols.js中保存了 React 不同组件类型的定义:
// ... export let REACT_ELEMENT_TYPE = 0xeac7; export let REACT_PORTAL_TYPE = 0xeaca; export let REACT_FRAGMENT_TYPE = 0xeacb; // ...这些以0xeac7形式存在的数字常量,是 React 内部用于标识element、portal、fragment等不同对象类型的 symbol。由于它是多个模块共用的“协议常量”,因此被集中放在shared中,避免各包重复定义造成不一致。
Renderer 相关的文件夹
如下几个文件夹为对应的Renderer:
- react-art - react-dom # 注意这同时是DOM和SSR(服务端渲染)的入口 - react-native-renderer - react-noop-renderer # 用于debug fiber(后面会介绍fiber) - react-test-renderer各 Renderer 面向不同的宿主环境:
- react-dom:面向浏览器 DOM,同时是客户端渲染与 SSR(服务端渲染)的入口;
- react-native-renderer:面向 React Native 的原生组件;
- react-art:面向 Canvas、SVG 或 VML(IE8);
- react-noop-renderer:不面向任何真实宿主,专门用于debug fiber——它渲染出纯 JS 对象,方便在测试与调试中观察 Reconciler 的工作过程;
- react-test-renderer:渲染出纯 JS 对象用于测试,是编写组件测试时的常用 Renderer。
在 React 15 的架构中(详见 docs/preparation/oldConstructure.md),Renderer 与 Reconciler 交替工作、递归更新 DOM,无法中断;而 React 16 中,Reconciler 为变化的虚拟 DOM 打上Placement、Update、Deletion等标记(全部标记见ReactSideEffectTags.js),所有协调工作都在内存中完成,最后才统一交给 Renderer 同步执行 DOM 操作。
试验性包的文件夹
React 将自己流程中的一部分抽离出来,形成可以独立使用的包。由于它们是试验性质的,不被建议在生产环境使用,包括如下文件夹:
- react-server # 创建自定义SSR流 - react-client # 创建自定义的流 - react-fetch # 用于数据请求 - react-interactions # 用于测试交互相关的内部特性,比如React的事件模型 - react-reconciler # Reconciler的实现,你可以用他构建自己的Renderer这些包是 React 内部能力的“对外暴露窗口”:例如react-reconciler可以让你基于它实现自己的 Renderer;react-server/react-client用于创建自定义的流式渲染。
注意:以下「辅助包」列表中同样出现了
react-client与react-fetch,说明在源码目录组织中,部分包既承担试验性职责,也被归类为辅助工具,读者只需理解其功能定位,不必纠结于分类边界。
辅助包的文件夹
React 将一些辅助功能形成单独的包,包括如下文件夹:
- react-is # 用于测试组件是否是某类型 - react-client # 创建自定义的流 - react-fetch # 用于数据请求 - react-refresh # "热重载"的React官方实现- react-is:提供类型判断工具(如
isValidElementType),用于测试组件是否属于某类型,是类型判断场景的标准工具; - react-refresh:React 官方的“热重载”实现,即 Fast Refresh,开发体验的核心支撑。
react-reconciler 文件夹:架构的枢纽
在以上所有 packages 中,react-reconciler是后续源码学习的重点,接下来源码学习中 80% 的代码量都来自这个包。
虽然它是一个实验性的包,内部的很多功能在正式版本中还未开放,但它扮演着承上启下的枢纽角色:
- 向上对接 Scheduler:
render阶段的入口performSyncWorkOnRoot与performConcurrentWorkOnRoot都定义在react-reconciler中,前者在同步更新时被调度,后者在异步更新时被调度。其中performConcurrentWorkOnRoot调用的workLoopConcurrent会在每轮遍历前通过shouldYield判断当前帧是否还有剩余时间(详见 docs/process/reconciler.md):
function workLoopConcurrent() { // Perform work until Scheduler asks us to yield while (workInProgress !== null && !shouldYield()) { workInProgress = performUnitOfWork(workInProgress); } }- 向下对接不同平台的 Renderer:Reconciler 在内存中完成“找出变化的组件”并为 Fiber 打上增/删/更新标记后,才将结果交给 Renderer 统一渲染,从而支撑可中断的异步更新。
正因如此,react-reconciler 一边对接 Scheduler,一边对接不同平台的 Renderer,构成了整个 React 16 的架构体系。后续章节对beginWork、completeWork、Fiber 树构建(详见 docs/process/fiber.md)等核心流程的讲解,绝大多数代码都来自这个包。
架构、术语与阅读路线
在继续深入源码前,有必要明确几个贯穿全书的术语(详见 docs/preparation/summary.md):
- Reconciler 工作的阶段被称为
render阶段:因为该阶段会调用组件的render方法; - Renderer 工作的阶段被称为
commit阶段:就像完成编码后执行git commit提交代码,commit阶段把render阶段提交的信息渲染到页面上; render与commit阶段统称为work,即 React 在工作中;如果任务正在 Scheduler 内调度,就不属于work。
结合上述文件结构,推荐的阅读路线是:
- 先读 docs/preparation/idea.md 理解 React 的“快速响应”理念(CPU 瓶颈与 IO 瓶颈);
- 再读 docs/preparation/newConstructure.md 与 docs/preparation/oldConstructure.md 对比 React 15 / 16 的架构差异;
- 回到本文掌握源码目录结构,带着“这个包属于哪一层”的意识去读源码;
- 按 docs/process/reconciler.md 与 docs/process/fiber.md 深入
render阶段,再进入 docs/renderer/prepare.md 了解commit阶段。
总结
通过本文,我们可以将 React 16 的三层架构精确映射到源码目录:
| 架构层 | 对应 packages | 职责 |
|---|---|---|
| Scheduler(调度器) | packages/scheduler | 时间切片 + 优先级调度 |
| Reconciler(协调器) | packages/react-reconciler | 找出变化的组件,打上增/删/更新标记 |
| Renderer(渲染器) | react-dom/react-native-renderer/react-art/react-noop-renderer/react-test-renderer | 将变化的组件渲染到宿主环境 |
支撑这三层运转的还有:提供全局 API 的react包、存放公共常量的shared包、以及若干试验性包(react-server、react-client、react-fetch、react-interactions)与辅助包(react-is、react-refresh)。
其中react-reconciler是理解整个 React 16 架构的钥匙——它一边对接 Scheduler,一边对接 Renderer,后续 80% 的源码学习都将围绕它展开。掌握了这份文件地图,后续深入 Fiber 与各个流程阶段时,就能始终清楚地知道“当前代码属于架构的哪一层”。
- 文档
- 前端
【免费下载链接】just-react
「React技术揭秘」 一本自顶向下的React源码分析书
相关推荐
Karakeep 源码仓库目录结构全解析:从 Apps、Shared Packages 到 Toolings 的 Monorepo 架构导览
Karakeep 源码仓库目录结构全解析:从 Apps、Shared Packages 到 Toolings 的 Monorepo 架构导览 本文以官方开发文档
后端前端移动开发AI 应用知识管理全文检索MCP 服务tchMaterial-parser一键下载电子课本PDF
tchMaterial parser一键下载电子课本PDF tchMaterial parser 是一款开源免费的 电子课本下载工具 ,面向国家中小学智慧教育平
文档前端Karakeep 仓库目录结构全解析:从 Apps、Shared Packages 到 Toolings 的 Monorepo 架构指南
Karakeep 仓库目录结构全解析:从 Apps、Shared Packages 到 Toolings 的 Monorepo 架构指南 本篇技术指南以 Kar
后端前端移动开发AI 应用知识管理全文检索MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考