React 源码解析:Fiber 架构、调度器、渲染流程

深入 React 源码核心原理,掌握 Fiber 架构、调度器(Scheduler)、协调器(Reconciler)、渲染器(Renderer),理解现代前端框架的设计哲学。

作者
React 源码解读专家React Contributor

🚀 React 架构设计

React 是声明式、组件化的 UI 库。React 16(Fiber)是一次完全重写,核心目标是可中断渲染、并发模式、更好的用户体验

2013
React 诞生
2017
Fiber 重构启动
2021
Concurrent Mode
2023
Server Components

React 核心模块

⚙️

react(核心库)

定义组件、Hooks、JSX 处理逻辑

🕒

react-reconciler

协调器(Fiber 架构、Diff 算法)

🎨

react-dom / react-native

渲染器(浏览器 DOM、Native 视图)

📦

scheduler(独立)

调度器(时间切片、优先级调度)

💡 独特观点

React 的真正创新不是"虚拟 DOM",而是调度能力。Fiber 让 React 能够中断、恢复、跳过渲染工作,从而实现并发模式。

🧵 Fiber 架构

Fiber 是 React 16 引入的全新协调引擎。它将渲染工作拆分成小单元,可以中断、恢复、优先级排序

1. Fiber 节点结构

📝 Fiber 节点(简化版)

// 每个 React 元素对应一个 Fiber 节点
function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // 1. 实例属性
  this.tag = tag;              // Fiber 类型(函数组件、类组件、DOM 节点)
  this.key = key;              // 唯一标识(列表 Diff)
  this.elementType = null;     // 元素类型(如 'div'、MyComponent)
  this.type = null;            // 函数/类本身
  this.stateNode = null;       // 对应的真实 DOM 节点或组件实例

  // 2. Fiber 链表结构(替代递归栈)
  this.return = null;          // 父 Fiber
  this.child = null;           // 第一个子 Fiber
  this.sibling = null;         // 下一个兄弟 Fiber
  this.index = 0;             // 在兄弟中的索引

  // 3. 副作用(Effect)
  this.flags = NoFlags;        // 副作用标志(插入、更新、删除)
  this.subtreeFlags = NoFlags; // 子树副作用
  this.deletions = null;       // 需要删除的子 Fiber

  // 4. 状态与 Props
  this.pendingProps = pendingProps;  // 新的 Props
  this.memoizedProps = null;        // 上一次的 Props
  this.memoizedState = null;        // 状态(Hooks 链表)
  this.updateQueue = null;           // 更新队列

  // 5. 替代(用于在渲染时保留旧 Fiber)
  this.alternate = null;        // 旧 Fiber(Double Buffer)
  
  // 6. 优先级相关
  this.lanes = NoLanes;        // 优先级车道
  this.childLanes = NoLanes;   // 子 Fiber 的优先级
}

2. Fiber 链表结构(替代递归)

Fiber 树结构(链表)
App (Fiber)
div (Fiber)
Header (Fiber)
Main (Fiber)
h1 (Fiber)
p (Fiber)
Footer (Fiber)

return(父) | child(第一个子) | sibling(下一个兄弟)

通过链表结构,React 可以中断遍历,之后从断点恢复。

3. Fiber 工作循环(Work Loop)

📝 简化版工作循环

// React 使用 "时间切片" 处理 Fiber 树
function workLoop(deadline) {
  let shouldYield = false;  // 是否应该让出主线程
  
  while (nextUnitOfWork && !shouldYield) {
    // 1. 执行一个 Fiber 单元的工作(Diff、渲染)
    nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
    
    // 2. 检查是否超时(应让出主线程给浏览器)
    shouldYield = deadline.timeRemaining() < 1;
  }
  
  if (!nextUnitOfWork) {
    // 2. 所有 Fiber 处理完毕,提交副作用(Commit)
    commitRoot();
  } else {
    // 3. 还有工作未完成,请求下一次时间切片
    requestIdleCallback(workLoop);
  }
}

// 执行一个 Fiber 单元的工作
function performUnitOfWork(fiber) {
  // 1. 处理当前 Fiber(Diff、创建 DOM)
  if (!fiber.dom) {
    fiber.dom = createDom(fiber);  // 创建真实 DOM
  }
  
  // 2. 协调子 Fiber(Diff 算法)
  reconcileChildren(fiber, fiber.children);
  
  // 3. 返回下一个要处理的 Fiber(深度优先遍历)
  if (fiber.child) {
    return fiber.child;  // 优先处理子节点
  }
  
  let nextFiber = fiber;
  while (nextFiber) {
    if (nextFiber.sibling) {
      return nextFiber.sibling;  // 处理兄弟节点
    }
    nextFiber = nextFiber.return;  // 回到父节点
  }
  
  return null;  // 遍历完成
}

📝 总结与展望

React 源码是现代前端框架的经典案例。通过本文的学习,你应该掌握了:

🎯 核心要点

  • Fiber 架构:链表结构、可中断渲染、时间切片
  • 调度器:优先级车道(Lanes)、时间切片、requestIdleCallback
  • 协调器:Diff 算法、Fiber 构建、副作用标记
  • 渲染器:Commit 阶段、DOM 操作、生命周期调用
  • JSX 转换:babel 插件、createElement、Fiber 构建
  • Diff 算法:同级比较、Key 优化、Fiber 复用
  • Hooks 原理:链表结构、useState/useEffect 实现
  • Concurrent Mode:Suspense、useTransition、useDeferredValue
  • 性能优化:memo、useMemo、useCallback、Code Splitting

🚀 未来展望

React 团队正在探索的方向:

  • Server Components:服务端组件(零客户端 Bundle)
  • Selective Hydration:选择性 hydrate(提升 TTI)
  • Offscreen API:后台渲染(类似 Resource Loading)
  • React Forget:编译器自动 memoization(无需手动优化)
  • React Canary:新特性预览(文档、Suspense 增强)