just-react 源码解析:React16 Fiber 架构的起源、含义与数据结构详解

发布时间:2026/10/8 8:03:15

just-react 源码解析:React16 Fiber 架构的起源、含义与数据结构详解 文档前端【免费下载链接】just-react「React技术揭秘」 一本自顶向下的React源码分析书项目地址https://gitcode.com/gh_mirrors/ju/just-react点击查看免费下载导读本文基于《React 技术揭秘》just-react仓库的 docs/process/fiber.md 展开系统讲解Fiber作为 React16 全新架构核心的来龙去脉它因何取代 React15 的虚拟 DOM 与递归 Reconciler作为「架构 / 静态数据结构 / 动态工作单元」的三层含义以及FiberNode构造函数的全部核心字段。读完本文你将掌握Fiber 树的连接方式return / child / sibling、静态与动态属性各自的职责边界以及lanes优先级模型取代expirationTime的演进背景为后续理解 render 阶段beginWork、completeWork与双缓存机制打下坚实基础。一、Fiber 的起源从「递归不可中断」到「异步可中断」在新的 React 架构一节中提到的虚拟 DOM在 React 中有个正式的称呼——Fiber。在后续学习中我们会逐渐用Fiber来取代「React16 虚拟 DOM」这一称呼。要理解Fiber因何而来需要先回顾 React15 的架构局限在React15及以前Reconciler协调器采用递归的方式创建虚拟 DOM递归过程是不能中断的。如果组件树的层级很深递归会占用线程很多时间造成卡顿。React 核心团队成员 Acdlite 在 2016 年发布的 react-fiber-architecture 是Fiber最早也是最具权威性的官方解释来源本文对 Fiber 的描述与之保持一致。为了解决「递归无法中断」的问题React16将递归的无法中断的更新重构为异步的可中断更新。由于曾经用于递归的虚拟 DOM数据结构已经无法满足「可中断、可恢复」的需求全新的Fiber架构应运而生。补充这种「异步可中断更新」本质上是在践行函数式编程中的代数效应Algebraic Effects思想。仓库的 fiber-mental.md 详细解释了为什么React没有采用Generator实现协调器Generator是「传染性」的且其中间状态是上下文关联的当高优先级任务插队时无法复用已计算的中间结果。React Fiber则是React内部实现的一套支持任务不同优先级、可中断与恢复、且恢复后可以复用之前中间状态的状态更新机制。二、Fiber 的三层含义Fiber并非一个单一概念它同时承载三层含义作为架构来说之前React15的Reconciler采用递归的方式执行数据保存在递归调用栈中所以被称为stack Reconciler。React16的Reconciler基于Fiber节点实现被称为Fiber Reconciler。作为静态的数据结构来说每个Fiber节点对应一个React element保存了该组件的类型函数组件 / 类组件 / 原生组件……、对应的 DOM 节点等信息。作为动态的工作单元来说每个Fiber节点保存了本次更新中该组件改变的状态、要执行的工作需要被删除 / 被插入页面中 / 被更新……。这层「架构 / 静态数据结构 / 动态工作单元」的分类将直接作为下文解析FiberNode各字段的线索。三、Fiber 的结构FiberNode 构造函数全解FiberNode的属性很多但可以按上述三层含义分类来看。核心定义对应 React 源码packages/react-reconciler/src/ReactFiber.new.js中的FiberNode构造函数如下function FiberNode( tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode, ) { // 作为静态数据结构的属性 this.tag tag; this.key key; this.elementType null; this.type null; this.stateNode null; // 用于连接其他Fiber节点形成Fiber树 this.return null; this.child null; this.sibling null; this.index 0; this.ref null; // 作为动态的工作单元的属性 this.pendingProps pendingProps; this.memoizedProps null; this.updateQueue null; this.memoizedState null; this.dependencies null; this.mode mode; this.effectTag NoEffect; this.nextEffect null; this.firstEffect null; this.lastEffect null; // 调度优先级相关 this.lanes NoLanes; this.childLanes NoLanes; // 指向该fiber在另一次更新时对应的fiber this.alternate null; }注仓库本身不包含 React 源码上述代码为《React 技术揭秘》依据 React 官方源码整理的结构字段含义与实际源码一一对应。当前本书对应版本为v17.0.0-alpha见 docs/index.md如需调试最新源码可参照 docs/preparation/source.md 中「拉取 master 分支 → 构建 react/scheduler/react-dom 三个包 → create-react-app 引用本地包」的流程。下面按三层含义逐一展开。四、作为架构Fiber 树的连接方式每个Fiber节点都有一个对应的React element多个Fiber节点通过如下三个属性连接成树// 指向父级Fiber节点 this.return null; // 指向子Fiber节点 this.child null; // 指向右边第一个兄弟Fiber节点 this.sibling null;为什么父级指针叫return而不是parent这是一个非常关键的设计细节因为Fiber是工作单元return指的是节点执行完completeWork后会返回的下一个节点。子Fiber节点及其兄弟节点完成工作后会返回其父级节点所以用return指代父级节点。这一命名体现了「Fiber 以工作流而非静态树为视角」的架构设计思想也与 docs/process/reconciler.md 中 render 阶段「递 / 归」两阶段的遍历方式直接对应。举例组件结构与 Fiber 树考虑如下组件结构function App() { return ( div i am spanKaSong/span /div ) }其对应的Fiber树结构为App Fiber父div Fiberchildi am Fiberchildspan Fibersibling即i am Fiber的右边第一个兄弟关于这棵 Fiber 树如何被深度优先遍历构建可参见 docs/process/reconciler.mdrender 阶段从rootFiber开始向下深度优先遍历为每个节点调用beginWork「递」与completeWork「归」两阶段交错执行直到归回rootFiber。五、作为静态的数据结构组件信息载体作为一种静态的数据结构Fiber保存了组件相关的信息// Fiber对应组件的类型 Function/Class/Host... this.tag tag; // key属性 this.key key; // 大部分情况同type某些情况不同比如FunctionComponent使用React.memo包裹 this.elementType null; // 对于 FunctionComponent指函数本身对于ClassComponent指class对于HostComponent指DOM节点tagName this.type null; // Fiber对应的真实DOM节点 this.stateNode null;各字段职责如下字段含义tagFiber对应组件的类型如FunctionComponent、ClassComponent、HostComponent等key组件的key属性用于 Diff 时识别节点elementType大部分情况与type相同某些情况不同例如FunctionComponent使用React.memo包裹时type对FunctionComponent指函数本身对ClassComponent指 class对HostComponent指 DOM 节点的tagNamestateNodeFiber对应的真实 DOM 节点佐证在 docs/process/beginWork.md 中beginWork正是根据workInProgress.tag的不同IndeterminateComponent、LazyComponent、FunctionComponent、ClassComponent、HostRoot、HostComponent、HostText等进入不同类型Fiber的创建逻辑最终统一进入reconcileChildren。六、作为动态的工作单元本次更新相关信息作为动态的工作单元Fiber中如下参数保存了本次更新相关的信息// 保存本次更新造成的状态改变相关信息 this.pendingProps pendingProps; this.memoizedProps null; this.updateQueue null; this.memoizedState null; this.dependencies null; this.mode mode; // 保存本次更新会造成的DOM操作 this.effectTag NoEffect; this.nextEffect null; this.firstEffect null; this.lastEffect null;这些属性会在后续的更新流程中用到时再详细介绍这里先建立整体认知pendingProps/memoizedProps分别保存「本次更新传入的新 props」与「上一次更新完成的 props」。在 docs/process/beginWork.md 的 update 优化路径中正是通过oldProps ! newProps即current.memoizedProps与workInProgress.pendingProps的比较判断是否可以直接复用current节点。updateQueue更新队列。在 docs/process/completeWork.md 中updateHostComponent处理完的 props 会被赋值给workInProgress.updateQueueupdatePayload为数组偶数索引是变化的 prop key奇数索引是变化的 prop value最终在 commit 阶段渲染到页面。memoizedState上一次更新完成的 stateHooks 相关章节会大量使用。effectTag/nextEffect/firstEffect/lastEffect保存本次更新会造成的 DOM 操作。effectTag使用二进制位表示例如// DOM需要插入到页面中 export const Placement /* */ 0b00000000000010; // DOM需要更新 export const Update /* */ 0b00000000000100; // DOM需要插入到页面中并更新 export const PlacementAndUpdate /* */ 0b00000000000110; // DOM需要删除 export const Deletion /* */ 0b00000000001000;通过二进制表示effectTag可以方便地使用位操作一次为fiber.effectTag赋值多个 effect如Placement | Update。佐证firstEffect/lastEffect与 docs/process/completeWork.md 中effectList机制直接相关——每个执行完completeWork且存在effectTag的Fiber节点会被保存在一条名为effectList的单向链表中第一个节点保存在fiber.firstEffect最后一个保存在fiber.lastEffect。这样 commit 阶段无需重新遍历整棵 Fiber 树只需遍历effectList即可执行所有 effect。调度优先级相关字段如下两个字段保存调度优先级相关的信息会在讲解Scheduler时详细介绍// 调度优先级相关 this.lanes NoLanes; this.childLanes NoLanes;⚠️ 注意优先级模型的历史演进在2020 年 5 月调度优先级策略经历了比较大的重构以expirationTime属性为代表的优先级模型被lane取代对应 React 官方 PR #18796。因此如果你的源码中fiber.expirationTime仍存在说明该版本早于这次重构请参照 调试源码章节 获取最新代码本书基于v17.0.0-alpha及以后版本讲解。仓库 docs/concurrent/lane.md 对lane模型有专门讲解docs/concurrent/scheduler.md则讲解Scheduler的原理与实现可与本节衔接阅读。alternate 属性双缓存机制的基石// 指向该fiber在另一次更新时对应的fiber this.alternate null;alternate虽然未在原文档的三层分类中单列但它是理解 Fiber 动态工作单元的关键补充current Fiber树中的current fiber与workInProgress Fiber树中的workInProgress fiber通过alternate属性连接currentFiber.alternate workInProgressFiber; workInProgressFiber.alternate currentFiber;这也是 docs/process/doubleBuffer.md 所讲的「双缓存」机制的核心React 在内存中构建workInProgress Fiber树构建完成后通过切换应用根节点fiberRootNode的current指针完成树的替换对应 DOM 的创建与更新。七、总结与下一步本节我们了解了Fiber的起源与架构起源React15 递归式stack Reconciler无法中断React16 将其重构为异步可中断的Fiber Reconciler三层含义作为架构Fiber Reconciler、作为静态数据结构保存组件类型、DOM 节点等信息、作为动态工作单元保存本次更新的状态改变与待执行工作结构FiberNode通过return / child / sibling三个属性连接成Fiber树通过tag / key / type / stateNode等保存组件信息通过effectTag等记录 DOM 操作通过lanes / childLanes表达调度优先级通过alternate衔接双缓存的两棵树。Fiber节点可以构成Fiber树。那么Fiber树和页面呈现的DOM树有什么关系React 又是如何更新 DOM 的呢这正是下一篇 docs/process/doubleBuffer.md双缓存机制要解决的问题而 Fiber 树在 render 阶段的具体构建过程则由 docs/process/reconciler.md、docs/process/beginWork.md、docs/process/completeWork.md 依次展开。参考资料《React 技术揭秘》Fiber 架构的实现原理本文主体Fiber 架构的心智模型代数效应、Generator 与 Fiber 的关系新的 React 架构Scheduler / Reconciler / Renderer 三层架构render 阶段流程概览「递 / 归」两阶段与 workLoopbeginWork递阶段的子 Fiber 创建与 effectTagcompleteWork归阶段的 DOM 创建与 effectList双缓存机制current / workInProgress 两棵 Fiber 树的切换原始出处Lin Clark - A Cartoon Intro to Fiber - React Conf 2017赞分享文档前端【免费下载链接】just-react「React技术揭秘」 一本自顶向下的React源码分析书项目地址https://gitcode.com/gh_mirrors/ju/just-react点击查看免费下载相关推荐图解 React 源码之高频对象ReactElement、Fiber、Update、Hook 与 Task 数据结构全解析图解 React 源码之高频对象ReactElement、Fiber、Update、Hook 与 Task 数据结构全解析 本文基于 react17.0.2教程前端Vue.js 源码解析Virtual DOM 与 VNode 数据结构详解Vue.js 源码解析Virtual DOM 与 VNode 数据结构详解 Virtual DOM 是 Vue.js 2.x 数据驱动架构的基石模板与数据最文档教程前端深入理解 JSX从编译产物到 React Element 与 Fiber 节点的源码级解析just-react 源码导读深入理解 JSX从编译产物到 React Element 与 Fiber 节点的源码级解析just react 源码导读 JSX 是 React 描述组件文档前端上一篇Fast-GitHub彻底解决国内访问GitHub缓慢的终极方案下一篇彻底卸载Microsoft Edge终极指南EdgeRemover脚本让你3分钟完成系统清理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/8 7:58:15

context-mode上下文治理:多场景模式设计与工程落地实践

1. 从"context-mode"说起:一个被低估的工程概念第一次看到"context-mode"这个词,很多人会下意识地把它归到某个具体框架的API文档里,觉得无非又是一个配置项。但如果你在工程一线待过几年,尤其是在做系统架构…

2026/10/8 7:58:15

context-mode 上下文模式设计:多场景配置隔离与动态切换实践

1. 从“context-mode”说起:一个被低估的工程概念第一次看到“context-mode”这个词,很多人会下意识地把它归到某个具体框架或库的配置项里去。但如果你在工程一线待过几年,就会发现这个词背后藏着一类非常普遍、却极少被系统讨论的问题&…

2026/10/8 9:03:30

保姆级教程:Windows下MySQL 9.1.0安装全流程解析

MySQL 9.1.0 发布之后,这段时间经常有人来问我同一个问题:不是问它跟 8.4 LTS 到底差多少,而是问“怎么装”。也确实,MySQL 官网的下载页对新手来说就是一本天书,一堆版本号横七竖八地排在那里,下面还有 ZI…

2026/10/8 9:03:30

HDMI2.1与eDP TX接口设计实战:从眼图测试到信号完整性排查

一块板子拿到手,第一次插上显示器就花屏或者直接黑屏,这种场景做硬件的人应该都不陌生。HDMI2.1、eDP这类高速视频TX接口,说难其实不算难,但坑的位置非常固定:高速差分信号怎么走、AC耦合电容放哪边、阻抗控制到多少、…

2026/10/8 9:03:30

双碳大模型实战:碳核算报告生成与CCUS比选

简介:一份聚焦大模型技术在碳排放与碳回收(双碳)领域应用的系统方案,内容从全球碳排放现状背景讲起,梳理工业化、能源消耗、交通、农业等主要驱动因素,并详细介绍化学吸收法、膜分离法、生物固定法、物理吸…

2026/10/8 9:03:30

OpenClaw(龙虾)部署实战:从Windows、安卓到腾讯云免费算力

说实话,我一开始看到“龙虾”OpenClaw全国巡装、腾讯云免费装机这种消息,第一反应是:这又是什么圈子里的新梗?结果顺着关键词一查,才发现这压根不是玩梗,而是一个正在快速升温的AI个人助理开发项目在往线下…

2026/10/8 9:03:30

Canal启动报错:Could not find first log file name 根因排查与解决

最近在帮团队搭建数据同步管道,启动Canal时报了一个看起来挺唬人的错误:Could not find first log file name in binary log index file。这个错误估计不少用过Canal的朋友都撞上过,第一次看到的时候我还愣了一下,毕竟Canal已经配…

2026/10/8 8:58:29

蠕虫病毒传播链与分层防御:从应急响应到内网加固实战指南

周五晚上十点,我正在家看球赛,手机突然连震三次。值班同事在群里发消息:核心交换机流量异常,内网大量主机互相发包,OA系统已经打不开了。紧接着远程连服务器,ssh敲下去卡了十几秒才出提示符,upt…

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/7 8:18:33

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:02:17

自然数立方等于连续奇数之和:从证明到编程验证

十几年来我一直游走在数学科普和编程教学这两块内容之间,对“看起来像魔法、拆开全是数学”的结论总是格外敏感。最近翻资料时又撞见一句话:任何一个自然数 m 的立方,都可以写成 m 个连续奇数之和。2 的立方等于 3 加 5,3 的立方等…

2026/10/8 0:02:17

C#上位机SSH连接实战:用SSH.NET补齐超时、批量与密钥认证

简介:这是一份基于 C# 开发的 SSH 连接功能半成品工程,原本作为另一个主项目的子功能模块,现独立打包分享。工程采用 WinForms 界面,包含源码、解决方案、安装部署工程、NuGet 依赖包及说明文档,适合正在做远程连接、网…

2026/10/8 0:02:17

Java SpringBoot一体化智能售后系统设计与实现全解析

毕业设计年年做,Java Web 方向的题目翻来覆去就那么几个,但“一体化智能售后系统”这个题,每次看到我都觉得值得认真聊一聊。它不是一个简单 curd 堆出来的管理系统,而是把客户、工单、派单、处理、回访、统计整条链路串起来的一套…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑