本页详解 React Native 旧架构的 Bridge 通信机制,介绍三线程模型的构成,以及 JSON 消息队列在序列化开销、异步延迟和单通道阻塞三方面带来的具体性能瓶颈。
三线程模型
旧架构(RN 0.68 及之前的默认模型,RN 0.73 之前无法完全绕开)运行在三条线程上:
| 线程 | 职责 |
|---|---|
| JS Thread | 执行 JavaScript bundle,运行 React reconciler、业务逻辑、事件处理 |
| UI Thread (Main Thread) | 执行真实的原生视图操作(UIKit / Android View),处理触摸事件 |
| Shadow Thread (Yoga Thread) | 运行 Yoga 布局引擎,将 React 的 flexbox 描述计算成具体尺寸,结果再传给 UI Thread |
三条线程不共享内存——这是旧架构最根本的设计约束,一切痛点都从这里派生。
JSON 消息队列的工作方式
JS Thread 与 UI Thread / Shadow Thread 之间唯一的通信通道是 Bridge:一条异步的序列化消息总线。
- JS 侧调用
NativeModules.SomeModule.someMethod(arg1, arg2)时,参数被序列化成 JSON 字符串,放入发送队列。 - Bridge 在适当时机(批量刷新,通常跟随 JS run loop)将队列里的消息跨线程投递给原生侧。
- 原生侧反序列化 JSON,执行对应的原生方法,结果再序列化回 JSON 投递回来。
- JS 侧在回调或 Promise 中收到结果,再次反序列化。
整个过程没有共享指针,没有直接的函数调用——所有数据都要经历两次 JSON 序列化/反序列化。
简化伪代码示例
// JS 侧——发出调用后立即返回,结果是异步的
NativeModules.Haptics.impact('medium', (result) => {
// 这个回调要等到 Bridge 投递完成才触发
// 在触摸事件发生到此回调之间,帧已经过去了
console.log(result);
});
// 原生侧无法被 JS 同步读取——下面的代码在旧架构不存在
// const width = NativeModules.Layout.getViewWidth(ref); // 不可能同步
三个具体性能痛点
1. 序列化开销
每次 JS 和原生之间传递数据都要序列化成 JSON、传输、再反序列化。对于高频操作(手势、动画每帧回调),这意味着每帧都在做大量字符串解析。Reanimated 1 之所以要把动画逻辑整个搬到原生侧执行,根本原因就是跨 Bridge 每帧传数据太慢。
2. 异步延迟,无法同步读原生状态
JS 侧无法同步获取原生视图的尺寸、滚动位置、输入框内容等状态。必须发消息 → 等回调。这导致一类典型问题:用户快速滚动时,JS 侧拿到的 scrollY 总是”过去”的值,实现视差滚动、吸顶效果时往往有抖动。
3. 单通道阻塞
Bridge 是单一的批量刷新通道,JS Thread 和 UI Thread 都往同一个队列里塞消息。当 JS 做大量计算(如渲染长列表)时,UI Thread 的消息处理也会积压——JS 卡顿直接导致 UI 掉帧,二者无法真正并发。新架构的 Concurrent Rendering(配合 Fabric)正是要解决这个问题:让渲染可中断,UI Thread 不被 JS 阻塞。
版本备注
- RN 0.68 及之前:Bridge 是唯一通道
- RN 0.69–0.72:可以开启新架构(实验性)但默认仍是旧架构
- RN 0.73–0.80:新架构可选,部分旧架构代码仍存在
- RN 0.81(Expo SDK 54):新架构默认开启,Bridge 代码在 Bridgeless 模式下完全不加载
参见
- RN 新架构组件详解
- RN 新架构验证方法
参考
版本说明
- 本页基于 2026-04-13 调研结果整理,适用范围以当前工具版本为准。