Fabric — 是新的 React Native 渲染器,完全用 C++ 重写并与 JSI 集成。它取代了基于 UIView 和 ViewManager 的旧渲染,通过 Shadow Tree 实现 UI 的同步更新和高效的变更计算。根据 Meta Engineering Blog, 2024,Fabric 是新架构的必需组件,在 React Native 0.76+ 中可用。
要点
Fabric — 是 React Native 的新渲染系统,取代了通过 Shadow Thread 和 Bridge 工作的旧渲染器。在旧架构中,渲染过程包括三个步骤:JavaScript 计算 Virtual DOM,Shadow Thread (Yoga) 计算布局,Native Thread 渲染 UIView。Fabric 将所有步骤合并到一个同步工作的 C++ 管道中。
Fabric 的开发始于 2019 年,是 Lean Core 计划和“新架构”项目的一部分。主要目标是解决与异步三阶段渲染相关的性能问题。在旧架构中,每次状态变更都需要通过不同线程进行三次传递,导致数据更改和 UI 渲染之间产生延迟。
Fabric 基于 不可变影子树 (Immutable Shadow Tree) 的概念。树的每个节点代表一个 React 组件及其 props 和状态。当状态改变时,会创建一个新树,Fabric 计算新旧树之间的差异,并仅将必要的更改应用于原生 UI。这最大限度地减少了 UIView/ViewGroup 操作的数量并缩短了渲染时间。
Shadow Tree — 是 Fabric 工作的基础。与旧架构(Shadow Tree 仅存在于 C++ 端并通过异步 Bridge 与 JS 树分离)不同,Fabric 创建了完全同步的层次化 UI 表示。Shadow Tree 的节点存储组件的 props、状态和样式,Yoga 直接在 C++ 级别计算布局。
当 React 组件更新其状态时,React Native 向 Fabric 发送新的 Shadow Node。Fabric 不会重新渲染整个 UI — 它使用 C++ 级别的比较算法(diffing)来确定哪些节点发生了变化。只有修改后的节点才会被发送到原生渲染,从而显著减少工作量。
Fabric 中的渲染过程包括三个阶段,在 C++ 级别同步执行,无需线程切换。第一阶段 — Render:React 调用组件的渲染函数,该函数返回 React Element Tree。第二阶段 — Commit:React Native 创建新的 Shadow Tree 并基于旧版本计算变更。第三阶段 — Mount:Fabric 将更改应用于原生 UI,创建、更新或删除 UIView。
所有三个阶段作为一个管道工作,数据通过 JSI 传输而无需序列化。这是与旧架构的关键区别,旧架构的各阶段之间存在中断:JS → (JSON) → Shadow Thread → (布局) → Native Thread。
Fabric 与旧渲染器的比较显示了 React Native 架构发生了多么显著的变化。旧渲染器异步工作,将渲染过程分为三个独立的线程。Fabric 将所有内容合并到一个 C++ 管道中。
| 特性 | 旧渲染器 | Fabric |
|---|---|---|
| 架构 | 三个线程(JS、Shadow、Native) | 统一的 C++ 管道 |
| 同步性 | 异步渲染 | 同步渲染 |
| Shadow Tree | 可变,每个线程有自己的副本 | 不可变,统一 |
| 通道 | Bridge + JSON 序列化 | JSI + 直接 C++ 调用 |
| 性能 | 每帧延迟高达 16 毫秒 | 每帧延迟低于 1 毫秒 |
在实践中,Fabric 对于具有频繁 UI 更新的应用程序特别有利:动画、带有浮动标题的滚动、实时数据。对于静态页面(文本、按钮),差异不太明显。根据 Meta 的基准测试,Fabric 将列表初始加载的渲染时间减少了 40–60%。
JSI (JavaScript Interface) — 是使 Fabric 成为可能的关键组件。通过 JSI,Fabric 无需序列化即可直接访问 JavaScript 值。当 React 将 props 传输到 Fabric 时,它们不会通过 JSON 复制 — JSI 传输指向 JS 引擎内存中数据的指针。
JSI 架构允许 Fabric 与任何 JavaScript 引擎(Hermes、JSC 或 V8)一起工作。Fabric 的 C++ 代码不依赖于 JS 引擎的特定实现,从而简化了维护和测试。所有与 UI 的操作(创建、更新、删除)都通过 JSI 执行,保证了最小的延迟。
// 通过 JSI 的 Fabric C++ 渲染管道
void mountShadowNode(
jsi::Runtime& runtime,
const ShadowNode::Shared& shadowNode,
const ShadowNode::SharedList& children
) {
auto props = shadowNode->getProps();
auto state = shadowNode->getState();
// 通过 JSI 同步传输 props
jsiValue.asObject(runtime)
.getProperty(runtime, "style")
.asObject(runtime);
// 直接通过 Yoga 计算布局
auto layoutMetrics =
YogaLayoutableShadowNode::layout(children);
// 将变更应用于原生 UI
UIManager::synchronouslyUpdateViewOnUIThread(
shadowNode->getTag(), layoutMetrics
);
}
主要优势 — 同步更新。在旧架构中,UI 通过异步队列更新:React 通过 Bridge 发送命令,Shadow Thread 处理布局,Native Thread 渲染。在 Fabric 中,所有步骤都在一次传递中顺序执行。这消除了竞态条件,并保证 UI 与应用程序的当前状态一致。
迁移到 Fabric 不需要重写 React 组件 — 所有现有的 React Native 组件继续工作。然而,带有原生代码的库(Native Module、自定义 ViewManager)可能需要更新。Meta 建议在启用新架构之前检查每个库的兼容性。
要在 React Native 0.76+ 项目中启用 Fabric,请在 react-native.config.js 中设置 newArchEnabled: true 标志。Fabric 将与 Turbo Module 一起自动启用。如果出现问题,可以禁用 Fabric 并返回旧渲染器,无需更改应用程序代码 — 两种架构并行支持。
// package.json — 检查与 Fabric 兼容的库
"react-native": "0.76.6",
"react-native-safe-area-context": "^5.0.0",
"react-native-screens": "^4.0.0",
"react-native-reanimated": "^3.16.0",
"react-native-gesture-handler": "^2.21.0"
迁移时,务必将所有原生库更新到与 Fabric 兼容的版本。大型库,如 react-native-reanimated 和 react-native-gesture-handler,已经支持新架构。对于尚未更新的库,Fabric 提供了兼容性机制 — 如果库不支持 Fabric,渲染器会自动切换到该库的旧渲染器。
常见问题
是的,从 Expo SDK 52 开始,新架构默认启用。Fabric 和 Turbo Module 在 managed workflow 中无需额外配置即可使用。
Fabric 凭借同步渲染显著改善了动画效果。JS 线程上的动画不再与 Bridge 消息处理竞争,从而消除了卡顿和 FPS 下降。
不需要,所有标准的 React Native 组件都可以与 Fabric 一起工作,无需更改。只有自定义的 ViewManager 需要更新以支持新架构。
在 react-native.config.js 中设置 newArchEnabled: false 并重新构建应用程序。所有模块和组件将继续无需更改地工作 — Fabric 和旧渲染器完全可以互换。
Bridgeless 模式 — Fabric 的一种工作模式,其中 Bridge 被完全禁用。所有通信仅通过 JSI 进行,从而提供最佳性能。在 React Native 0.76+ 中可用。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。