RN 常见性能问题:JS卡顿、UI卡顿、桥接通信耗时

RN(React Native)性能问题,基本可以归纳成三个核心方向:JS 卡顿、UI 卡顿、JS ↔ Native 桥接通信耗时。这三个问题经常互相影响,但排查思路并不一样。

1. JS 卡顿:JavaScript 线程忙不过来

RN 中大量业务逻辑运行在 JS Thread。如果 JS 线程长时间执行任务,就会出现:

  • 点击后很久才响应
  • 动画掉帧
  • FlatList 滑动不流畅
  • 手势响应延迟
  • setState 后 UI 更新迟缓
  • 定时器、Promise 回调堆积

典型问题:

c 复制代码
const result = hugeArray.map(item => {
  // 大量计算
  return heavyCalculate(item);
});

或者:

ini 复制代码
JSON.parse(largeJson);
JSON.stringify(hugeObject);

以及:

css 复制代码
for (let i = 0; i < 10000000; i++) {
  // CPU 密集型任务
}

核心原则:不要让 JS Thread 长时间同步执行重计算。

常见优化:

复制代码
重计算
 ↓
拆分任务
 ↓
减少计算量
 ↓
缓存结果
 ↓
避免无意义 render
 ↓
必要时交给 Native / JSI / Worklet

2. UI 卡顿:Native UI Thread 掉帧

UI 卡顿和 JS 卡顿不是一回事。

例如:

markdown 复制代码
JS Thread       正常
     ↓
UI Thread       忙于布局 / 绘制
     ↓
FPS ↓
     ↓
用户看到掉帧

常见原因:

① 页面组件太多

例如一个页面同时渲染几百个 View。

② FlatList 使用不当

ini 复制代码
<FlatList
  data={data}
  renderItem={renderItem}
/>

如果数据量很大,需要重点考虑:

ini 复制代码
<FlatList
  data={data}
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
  removeClippedSubviews
/>

同时避免:

ini 复制代码
renderItem={() => <ComplexComponent />}

每次 render 都创建大量对象、函数或者复杂组件。

③ 图片太大

比如:

yaml 复制代码
原图 4000 × 3000
        ↓
RN 页面只显示 200 × 150
        ↓
仍然加载超大图片
        ↓
解码 + 内存 + GPU 压力

图片性能经常是移动端 UI 卡顿的隐藏杀手。


3. 桥接通信耗时:JS ↔ Native

这是 RN 早期架构中非常典型的问题。

传统架构可以简单理解成:

arduino 复制代码
JavaScript
    │
    │ Bridge
    ↓
Native
    │
    ↓
UI

如果 JS 和 Native 之间频繁传输大量数据:

arduino 复制代码
JS
 ↓
Bridge
 ↓
Native
 ↓
Bridge
 ↓
JS
 ↓
Bridge
 ↓
Native

就容易产生明显开销。

例如:

ini 复制代码
NativeModule.sendHugeData(largeObject);

如果 largeObject 非常大,而且调用频率很高,就可能造成性能问题。

尤其是这种模式:

scss 复制代码
for (...) {
  NativeModule.doSomething();
}

比:

ini 复制代码
NativeModule.doBatchSomething(data);

更容易产生通信开销。

核心原则:减少 JS ↔ Native 通信次数,同时减少传输数据量。


4. 新架构:Bridge 不再是唯一核心

现在 RN 性能优化不能只盯着传统 Bridge。

React Native 新架构主要涉及:

复制代码
JSI
Fabric
TurboModules
Hermes

可以简单理解:

arduino 复制代码
旧架构

JS
 │
Bridge
 │
Native

而新架构更加倾向于:

复制代码
JS
 │
JSI
 │
Native

因此一些过去严重依赖 Bridge 的性能问题,在新架构下会得到改善。

但这并不意味着:

"用了新架构,RN 就不会卡。"

实际上:

JS 重计算依然会卡。

Native UI 渲染压力依然会卡。

大量数据传递依然可能造成性能问题。

所以 RN 性能优化最终还是要回到:

markdown 复制代码
JS 性能
   +
React Render 性能
   +
UI / Layout 性能
   +
Native 性能
   +
通信性能
   +
内存
   +
图片

5. 面试/实际项目可以这样建立排查思路

遇到:

"RN 页面很卡"

不要直接开始改代码,而是先判断到底是谁卡了

markdown 复制代码
                 页面卡顿
                    │
          ┌─────────┴─────────┐
          ↓                   ↓
       JS 卡顿              UI 卡顿
          │                   │
   JS 是否长任务?       Layout 是否复杂?
   是否频繁 render?     图片是否过大?
   是否大量计算?       列表是否优化?
          │                   │
          └─────────┬─────────┘
                    ↓
              JS ↔ Native
                 是否频繁通信?
                    │
                    ↓
              内存 / 图片 / IO

一句话总结

问题 主要表现 优化方向
JS 卡顿 点击延迟、动画不响应 减少 JS 重计算、减少 render
UI 卡顿 掉帧、滑动不流畅 优化布局、列表、图片、绘制
桥接耗时 JS/Native 交互慢 减少通信次数和数据量
内存问题 页面越来越卡甚至崩溃 图片、缓存、组件生命周期
React Render 状态变化导致大量组件更新 memo、拆组件、状态下沉
列表性能 长列表 FPS 下降 FlatList/FlashList、虚拟化
新架构问题 某些 Native 模块性能异常 JSI、TurboModule、Fabric
相关推荐
BreezeJiang43 分钟前
别再背工厂模式了:NestJS 第一行代码就是它的工业级落地
前端·javascript
liuxiaocheng1 小时前
文本生成的进阶:generateText / streamText 里迟早会撞上的东西
前端·后端·ai编程
渣波1 小时前
深度解析工厂模式:从蜜雪冰城到 NestFactory,彻底搞懂“创建与使用分离”
前端·javascript
蔓越莓1 小时前
打包工具:编译器ESBuild
前端·面试
用户921080262861 小时前
Bubble 的 loading 和 typing:AI 回复生成中的交互处理
前端
SamChan901 小时前
用Playwright端到端测试PDF翻译功能:Web自动化测试实战
前端·python·ai·pdf·wpf
平生不晚1 小时前
在 SVG 体系里画一条任意的线
前端·算法
用户059540174461 小时前
把大模型记忆召回测试从 30 分钟手工核对压到 3 秒自动化,pytest + FAISS 这套组合救了我
前端·css
醉里博客1 小时前
醉里起始页 Snavigation2.0:纯前端导航页的二开改造与性能优化实践
前端