什么是 Fiber?
Fiber 是 React 16 引入的全新渲染引擎,它的核心目标是解决大型应用中的性能瓶颈。在 Fiber 之前,React 的递归更新方式是同步且不可中断的,这意味着一旦更新开始,就必须完成整个组件树的渲染——这会导致长时间的主线程阻塞,造成页面卡顿。
Fiber 将渲染任务拆分成小的单元,使得更新可以暂停、恢复和复用,从而实现了可中断的异步渲染。
为什么需要 Fiber?
React 15 及之前的问题
在旧版 React 中,更新过程是这样的:
// 伪代码:同步递归更新
function updateComponent(component) {
render(component);
component.children.forEach(updateComponent); // 递归
commit(component);
}
问题很明显:
- 不可中断:一旦开始更新,必须走完整个组件树
- 主线程阻塞:大型组件树可能导致几百毫秒的卡顿
- 无法优先处理紧急任务:用户输入和动画必须等待更新完成
Fiber 的解决方案
Fiber 将更新任务拆分成多个小任务单元,每个单元对应一个 Fiber 节点。React 可以在执行完一个单元后检查是否有更高优先级的任务,如果有就暂停当前工作,先处理紧急任务。
// 伪代码:可中断的更新循环
function workLoop() {
while (hasNextUnit && !shouldYield()) {
performUnitOfWork(nextUnit);
}
if (hasNextUnit) {
requestIdleCallback(workLoop); // 空闲时继续
}
}
Fiber 的数据结构
每个 Fiber 节点是一个 JavaScript 对象,包含组件的完整信息:
interface Fiber {
// 类型标识
tag: WorkTag;
// 组件实例和 DOM 节点
stateNode: any;
// 子节点和兄弟节点(链表结构)
child: Fiber | null;
sibling: Fiber | null;
return: Fiber | null;
// 当前工作节点和备用节点(双缓冲)
current: Fiber | null;
alternate: Fiber | null;
// 更新队列
updateQueue: UpdateQueue | null;
// 状态和属性
memoizedState: any;
memoizedProps: any;
// 优先级相关
lanes: Lanes;
priority: number;
}
关键点:
- 链表结构:用
child、sibling、return代替递归,方便遍历和暂停 - 双缓冲:每个组件有两个 Fiber 节点,一个当前显示,一个正在构建
- 更新队列:存储待处理的更新,支持批量和优先级调度
Fiber 的工作流程
React 的渲染分为两个阶段:
1. Render 阶段(可中断)
构建 Fiber 树并计算变更:
beginWork() → 处理当前节点
↓
completeWork() → 完成当前节点
↓
commitRoot() → 提交到 DOM(如果完成)
这个阶段可以暂停,React 会记录进度以便恢复。
2. Commit 阶段(不可中断)
将变更应用到 DOM:
beforeMutation → mutation → layout
这个阶段必须同步完成,确保 UI 一致性。
优先级调度
Fiber 支持多种优先级:
| 优先级 | 场景 |
|---|---|
| Immediate | 文本输入、紧急交互 |
| UserBlocking | 按钮点击、滚动 |
| Normal | 数据获取、普通更新 |
| Low | 后台任务 |
| Idle | 空闲时执行 |
高优先级任务可以打断低优先级任务的执行:
// 伪代码:优先级检查
if (higherPriorityTaskExists()) {
yield(); // 让出主线程
scheduleCallback(higherPriorityTask);
}
实际影响
对开发者的意义
- Concurrent Mode:
useTransition、useDeferredValue等 API 的基础 - Suspense:组件级加载状态,无需手动管理 loading
- 更好的用户体验:用户输入不会因渲染而卡顿
示例:使用 useTransition
import { useTransition, useState } from 'react';
function SearchResults() {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
const [results, setResults] = useState([]);
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
// 将耗时更新标记为低优先级
startTransition(() => {
const filtered = heavyFilter(value);
setResults(filtered);
});
};
return (
<>
<input value={query} onChange={handleChange} />
{isPending && <Spinner />}
<Results data={results} />
</>
);
}
输入框立即响应,搜索结果在后台计算,不会阻塞用户输入。
总结
Fiber 是 React 性能优化的核心:
- ✅ 可中断渲染:避免长任务阻塞主线程
- ✅ 优先级调度:紧急任务优先处理
- ✅ 并发特性:为 Concurrent Mode 奠定基础
- ✅ 更好的用户体验:流畅的交互和动画
理解 Fiber 有助于写出更高效的 React 应用,尤其是在处理大型组件树和复杂交互时。
参考资料: