首页 / 文章 / Nitro 模块:静态绑定为何优于 React Native TurboModules

Nitro 模块:静态绑定为何优于 React Native TurboModules

解释了 Nitro Modules 如何通过使用预编译的静态绑定而非动态查找,在 React Native 中显著优于 TurboModules 和 Expo Modules。

1178 词

TurboModules本应成为解决方案。它取代了过时的桥接架构,去除了不必要的开销,成为了编写能与JavaScript交互的本地代码的公认方法。后来出现了一个名为Nitro Modules的新库,使得那个“最终答案”显得过时了。

已公布的测试结果显示,在对相同的同步函数调用进行测试时,Nitro Modules的性能可比Expo Modules高出59倍,相比TurboModules则高约15倍。即便涉及字符串处理——这类操作在JavaScript与原生代码之间转换时通常会增加开销——Nitro依然能保持5到13倍的性能优势。当处理图像或原始缓冲区等更大规模的数据时,得益于避免在内存中重复数据的零复制机制,Nitro的性能还能进一步提升8%到40%

如此惊人的数据需要一个解释:Nitro在底层究竟做了什么?为何这种设计没有更早出现?

其他人尚未解决的问题

Nitro并非作为基准测试工具而设计的。它是VisionCamera的创建者Marc Rousavy为解决一个非常具体的问题而开发的:无论是TurboModules还是Expo Modules都无法妥善处理帧处理功能。

在VisionCamera中,单个相机帧可以被视作一个约10兆字节的缓冲区。即便使用TurboModules,这个缓冲区也无法被传输到另一端,而且它也不适合放入普通的JSON结构中。Rousavy真正需要的是一种方法,能够将用C++或Swift编写的复杂、带状态的原生对象直接传递给JavaScript,同时保留其方法与属性功能。而TurboModules并不具备处理这类对象的机制。

Nitro正是为了解决这一问题而专门设计的,其带来的显著速度提升虽然只是附加效果,却吸引了远超过它原本要解决的问题的关注度。

一个架构上的选择

TurboModules与Nitro之间的真正差异在于一个设计决策:即每种系统在JavaScript引擎内部如何表示原生对象。

TurboModules依赖于jsi::HostObject。每当JavaScript代码访问这些对象上的属性或调用其方法时,运行时必须即时动态地解析该访问请求。每次调用都会进行这样的查找,对于频繁被调用的模块而言,这种重复的开销会迅速累积起来。

Nitro采取了不同的路径,它使用jsi::NativeState。结合名为Nitrogen的代码生成工具,它在应用程序运行之前就预先生成所有必要的C++、Swift或Kotlin绑定代码。在运行时没有任何内容是动态解析的。JavaScript与原生类型之间的转换是在事先静态编译完成的,这意味着调用Nitro模块的行为更像是调用普通函数,而非通过运行时桥接来实现。

正是这一变化——用预编译的静态绑定替代动态运行时查找——导致了基准测试中显示的大部分性能差异。

在 Nitro 中,无论用 C++、Swift 还是 Kotlin 编写的任何原生对象都被称为混合对象。Nitrogen 会解析 TypeScript 接口定义,并自动生成将该对象跨 JS 原生边界传输所需的代码,同时还能处理枚举、联合类型和结构体等。正是这样的工具让 Rousavy 能够直接展示实时摄像头画面这类非传统内容,而无需为三个平台分别编写独立的桥接代码。

为何这超越了普通库的范畴

VisionCamera证明了这种方法的可行性,但Nitro的设计从一开始就不是为了解决某一个特定场景而设计的临时方案。它的架构为任何原生模块提供了对数组缓冲区、带状态的原生对象以及直接C++互操作的内置支持,而这些功能在之前的方法中要么实现起来极为笨拙,要么根本无法使用。

更广泛的 React Native 生态系统已经开始关注这一趋势。诸如 react-native-nitro-cache 这样的项目,以及那些用于图像缓存、机器学习任务和游戏引擎的工具,都在基于 Nitro 进行重构,旨在在最需要提升性能的场景中减少 JavaScript 转换为原生代码的开销。这反映了 React Native 整体正在出现的更大趋势:各类基础库都在围绕 新架构 进行重构,而非将其视为日后可选采用的方案。尽管 Nitro 的采用率仍远低于 TurboModules——后者依然是大多数库的默认选择——但其发展势头十分明显。在任何对性能要求极高的场景中,Nitro 正逐渐成为开发者首先考虑的工具。

这对原生模块开发者意味着什么

如果您目前正在使用原生模块,这一变化值得您关注。TurboModules短期内不会消失,对于那些结构简单的模块,性能差异很可能不会被最终用户察觉。但如果您使用的模块涉及对性能要求较高的操作、高频调用、大量数据传输,或是无法完整映射为JSON的对象,Nitro现在很可能是更适合作为基础的选择

在2026年选择在TurboModules上开发全新的原生模块,实际上意味着要在一种已被更快且仍在发展的替代方案超越的架构之上进行构建。Nitro的代码生成工具能够同时自动处理三大平台上的大量重复性工作,最终生成的程序运行速度更快,且需要维护的手写原生代码更少。对于已经使用TurboModule的团队而言,迁移并非简单的开关操作,但正是让Nitro具有吸引力的那些性能测试结果,也为尽早安排迁移提供了充分理由。

React Native已经经历过几次真正的架构转折点:旧架构的废弃、新架构的引入,以及现在的这一次。Nitro并非在Meta的官方指令下诞生的,它出现的原因是有位开发者需要TurboModules无法提供的功能,于是他公开开发了这一解决方案,并让测试结果自行说明问题。

相关阅读

  • React 19.2详解:Activity、useEffectEvent与静态渲染 — 了解React 19.2中的新Activity组件、useEffectEvent钩子以及部分静态渲染功能如何解决现代用户界面中存在的隐性性能问题。
  • 为何Shopify放弃React Native并不威胁Expo — 阐述了Shopify从React Native转向原生Swift和Kotlin为何并不意味着大多数团队跨平台开发工具Expo的终结。
  • 在React Native中构建可处理大文件的防崩溃PDF阅读器 — 了解如何在React Native中实现渲染数千页大型PDF的架构,包括懒加载书签结构、搜索功能以及在低端设备上的稳定导航。
  • React Native内存泄漏问题:追踪JS堆与原生内存的占用者 — 了解为何垃圾回收机制无法解决React Native应用中的原生层内存泄漏问题,以及如何找出导致回调函数、JSI对象和解码后的图像持续存在的原因。
  • 为何 Codegen 要让 React Native TurboModules 必须遵循“先写规范”的原则 — 了解 React Native Codegen 如何将 TurboModule 的 TypeScript 规范转化为构建时的契约,省略该步骤会带来哪些问题,以及此规则在何处不再适用。