React Native 架构演进:从 Bridge 通信到 JSI 与新架构(Fabric/TurboModules)

28 阅读3分钟

1. 为什么需要了解架构?

作为一名 Android 工程师,你深知 UI 线程(Main Thread)被阻塞会导致掉帧(ANR 或卡顿)。在 React Native 中,JavaScript 代码和原生的 Android/iOS 代码是运行在不同线程的,它们之间的通信机制直接决定了应用的性能。

2. 旧架构:Bridge 时代

在很长一段时间里,RN 依赖一个名为 Bridge 的机制进行通信。

它是如何工作的?

  • JS 线程计算出 UI 的变更(比如要渲染一个按钮)。
  • 这些变更会被序列化成 JSON 字符串。
  • JSON 字符串通过 Bridge 发送到原生(Android)线程。
  • 原生线程解析 JSON,然后调用 Android 原生的 Button 控件进行渲染。

痛点(为什么被吐槽慢?)

  1. 异步通信:JS 和 Native 的通信是异步的。如果 JS 想获取原生视图的尺寸,它必须发送请求,等待下一帧原生返回结果,这就导致了诸如手势动画延迟、列表滑动白屏等问题。
  2. 序列化开销:大量数据的 JSON 序列化和反序列化非常耗时,尤其是在老旧的 Android 手机上。

类比 Android:这就像是在两个不同的进程之间,只能通过把对象转成 JSON 字符串,然后用 Intent 传过去一样,效率极低。

3. 破局者:JSI (JavaScript Interface)

为了解决 Bridge 的问题,RN 引入了 JSI(基于 C++)。

核心改变

JSI 允许 JS 引擎(如 Hermes)直接持有 C++ 对象的引用,并直接调用其方法,无需序列化为 JSON。由于 Android (JNI) 也能与 C++ 互通,这意味着 JS 可以几乎同步地调用 Android 原生方法!

类比 Android:这就好比你使用 JNI 直接在 Java 中调用 C++ 函数,虽然有微小的 JNI 开销,但没有序列化负担,而且是同步的。

4. 新架构双子星:Fabric 与 TurboModules

有了 JSI 这个底层基石,RN 团队重写了 UI 渲染和原生模块层。

Fabric (新 UI 架构)

  • 直接调用:JS 可以直接通过 JSI 创建和更新原生 UI 节点。
  • 同步渲染:JS 现在可以同步测量原生视图的尺寸。当你滚动列表时,UI 和 JS 逻辑可以保持在同一帧内,彻底消除了异步带来的卡顿。
  • 类比 Compose:Fabric 让 RN 的 UI 树更新过程更像 Compose,由状态驱动,并高效、同步地计算 Diff。

TurboModules (新原生模块)

在旧架构中,所有的原生模块(如蓝牙、相册)在应用启动时就会全部初始化,拖慢启动速度。

  • 懒加载:通过 JSI,JS 只有在第一次调用该模块时,TurboModules 才会去初始化对应的 Android 原生模块。
  • 强类型:通过 Codegen 工具,可以在编译期保证 JS 调用原生方法时的类型安全(不会出现 JS 传了 String,Android 期望 Int 导致的 Crash)。

5. 总结

RN 已经摆脱了“Bridge 通信慢”的历史包袱。基于 JSI 的新架构(Fabric/TurboModules)在底层通过 C++ 打通了 JS 和 Native 的壁垒,使得 RN 在动画处理、手势响应等重度交互场景下的性能已经非常接近原生 Android 和 Compose。作为原生开发者,现在拥抱 RN 正是最好的时机。