【前端架构和框架】react整体架构

120 阅读6分钟

React 18 的整体架构设计是在 React 16 引入的 Fiber 架构基础上,通过增强并发渲染能力、优化调度机制和扩展核心 API 实现的重大升级。其核心目标是支持并发渲染、异步可中断式更新 ,让应用在处理复杂计算或大量 UI 更新时仍能保持流畅的用户交互。

一、整体架构设计:三层核心架构 + 并发能力扩展

React 18 的架构可分为应用层、核心层、平台层三大层级,各层级职责明确且协同工作:

┌───────────────── 应用层 ─────────────────┐
│ 组件(函数/类)、Hooks、状态管理           │
│ 新增:并发特性 API(useTransition 等)    │
├───────────────── 核心层 ─────────────────┤
│ 调度器(Scheduler):任务优先级与中断控制  │
│ 协调器(Reconciler):Fiber Diff 与更新计划 │
│ 渲染器(Renderer):提交更新与平台渲染    │
├───────────────── 平台层 ─────────────────┤
│ Web(DOM)、Native(React Native)等     │
└──────────────────────────────────────────┘

1. 核心设计理念

  • 并发渲染(Concurrent Rendering) :允许渲染过程被中断、暂停、恢复甚至放弃,优先处理高优先级任务(如用户输入)。
  • 优先级驱动:通过细粒度的优先级体系,动态调整任务执行顺序。
  • 向后兼容:在保留 React 16 核心能力(如 Fiber 架构)的基础上扩展新特性,确保现有应用平滑迁移。

二、核心层实现细节

1. 调度器(Scheduler):任务优先级与执行控制

调度器是并发渲染的 “大脑”,负责决定何时执行哪个任务,核心实现包括:

  • 优先级体系:定义了 5 级优先级(从高到低):

    • Immediate:同步执行,最高优先级(如用户输入事件)。
    • UserBlocking:用户阻塞级(如点击、滚动等交互),需在 25ms 内完成。
    • Normal:普通优先级(如网络请求后的 UI 更新)。
    • Low:低优先级(如非紧急的数据处理)。
    • Idle:空闲时执行(如日志上报)。
  • 时间切片(Time Slicing) :基于 MessageChannel 实现(替代 React 16 的 requestIdleCallback),将长任务拆分为多个小任务,每个任务执行不超过 5ms,避免阻塞主线程。

  • 任务中断与恢复:维护任务队列,高优先级任务可中断低优先级任务,低优先级任务在后续空闲时从断点恢复执行。

2. 协调器(Reconciler):Fiber 架构与并发 Diff

协调器负责对比新旧虚拟 DOM(Fiber 树),生成更新计划,核心实现:

  • Fiber 数据结构:每个 Fiber 节点对应一个组件,包含:

    {
      type: 组件类型(如 div、FunctionComponent),
      props: 组件属性,
      stateNode: 真实 DOM 节点(或组件实例),
      child:  Fiber 节点,
      sibling: 兄弟 Fiber 节点,
      return:  Fiber 节点,
      effectTag: 更新标记(如插入、删除、更新)
      ......
    }
    
  • 并发 Diff 算法

    • 与 React 16 的同步 Diff 不同,React 18 的 Diff 过程可被中断:遍历 Fiber 树时,每处理一个节点就检查是否有高优先级任务,若有则暂停当前 Diff,保存进度后让出主线程。
    • 恢复时从上次中断的 Fiber 节点继续处理,避免重复计算。
  • 优先级排序:协调器会根据任务优先级优先处理高优先级 Fiber 节点(如用户输入触发的组件更新),低优先级节点可延迟处理。

3. 渲染器(Renderer):并发提交与批处理优化

渲染器负责将协调器生成的更新计划应用到实际平台(如 DOM),核心实现:

  • 并发提交(Concurrent Commit)

    • 提交阶段是 “原子操作”(不可中断),但 React 18 支持 “选择性提交”:仅提交高优先级更新,低优先级更新暂存,避免因混合优先级更新导致的 UI 闪烁。
    • 通过 “双缓存机制” 维护当前屏幕上的 Fiber 树(current)和正在构建的 Fiber 树(workInProgress),提交时只需切换指针即可。
  • 自动批处理(Automatic Batching)

    • React 16 仅在 React 事件回调中支持批处理(合并多次 setState)。
    • React 18 扩展到全场景:setTimeoutPromise.then、异步函数等场景下的多次状态更新会自动合并,减少 DOM 操作次数。
  • 多根渲染(Multiple Roots) :通过 ReactDOM.createRoot 支持同一页面渲染多个独立根节点,共享调度和协调逻辑,适合大型应用的模块化拆分。

三、应用层:并发特性 API

React 18 新增了一批 API 让开发者直接控制并发渲染,核心包括:

  1. ReactDOM.createRoot:替代 ReactDOM.render,是开启并发模式的入口:

    // React 16
    ReactDOM.render(<App />, document.getElementById('root'));
    
    // React 18
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<App />);
    
  2. useTransition:将非紧急更新标记为 “过渡更新”(低优先级),避免阻塞用户交互:

    const [isPending, startTransition] = useTransition();
    
    // 高优先级:输入框更新
    setInputValue(input);
    
    // 低优先级:过滤列表(被标记为过渡更新)
    startTransition(() => {
      setFilteredList(filterList(input));
    });
    
  3. useDeferredValue:为状态生成延迟版本,自动适配并发渲染的中间态:

    // 原始状态(高优先级)
    const [query, setQuery] = useState('');
    // 延迟状态(低优先级,自动跟随 query 更新)
    const deferredQuery = useDeferredValue(query);
    
    // 用延迟状态渲染非紧急 UI(如长列表)
    return <List items={filterItems(deferredQuery)} />;
    

四、关键流程:从更新触发到渲染完成

以用户输入触发更新为例,React 18 的核心流程如下:

  1. 触发更新:用户输入(如点击按钮)调用 setState 或 useState 的更新函数。
  2. 创建更新对象:创建Update对象和优先级,把更新对象加入到当前fiber节点的更新队列中(updateQueue内部是个链表结构)。
  3. 冒泡到根节点:markUpdateLaneFromFiberToRoot调用,从当前fiber把本次更新的优先级冒泡到根节点。
  4. 调度任务:调度器根据更新来源(如用户交互)分配高优先级,将任务加入队列。
  5. 并发协调:协调器启动 Fiber Diff,遍历组件树生成更新计划,过程中若有更高优先级任务则中断并让出主线程。
  6. 提交更新:协调完成后,渲染器将高优先级更新批量提交到 DOM,低优先级更新暂存。
  7. 清理与恢复:高优先级任务完成后,调度器恢复低优先级任务的协调与提交。

684cde13-93ae-46ad-9ce4-b664a7135684.jfif

上图是我从社区看到的,把react整体的运行流程基本上画的很清晰,这边就是为了看的明白些,就不自己在重新画了。

五、总结

React 18 的架构设计围绕 “并发渲染” 展开,通过:

  • 调度器实现任务优先级与中断控制;
  • 协调器基于 Fiber 架构支持并发 Diff;
  • 渲染器优化提交逻辑与批处理;
  • 应用层 API 让开发者掌控渲染优先级。

这一架构使 React 应用在处理复杂场景(如大数据渲染、高频交互)时,既能保证用户体验流畅,又能兼顾开发效率,是 React 从 “同步渲染” 到 “可控并发渲染” 的里程碑升级。