构建高性能的 React Native 应用
Source: Dev.to
请提供您希望翻译的具体内容,我将为您翻译成简体中文,并保持原有的格式、Markdown 语法和技术术语不变。
概览
在决定提升性能之前,先了解应用的哪一部分真的慢。
- React Debugger – 帮助你发现耗时的重新渲染、首次加载时间以及页面挂载/卸载状态。
不要低估它的价值;它可以显著提升性能。

如果想超越 JavaScript 层面,你可以使用 Xcode 或 Android Studio 对应用进行原生分析。原生分析可以让你看到:
- 总内存使用量
- 某个特定页面或操作的内存消耗
- 原生内存泄漏
- CPU 使用率
原生分析是可选的,如果你的应用没有执行大量操作(例如视频渲染或 3D 图形),可以跳过。
你可以使用 Android Studio 或 Xcode 等 IDE 对应用进行原生分析。这样做可以让你清晰了解整体内存使用情况、原生泄漏以及 CPU 负载。


此时,你应该已经对应用的哪一部分慢有了大致了解。接下来我们来讨论如何以及怎样进行优化。
渲染大型列表
渲染列表可能具有挑战性。如果你的项目项很简单,使用 FlatList 或 FlashList(Shopify)。两者都是处理中等规模列表的直接方案。
当每个项的渲染需要显著时间(例如约 400 ms)时,问题就会出现。FlatList 的虚拟化会在用户滚动时添加/移除项,这会导致 CPU 正忙于虚拟化,从而出现可见的空白。
解决方案
| Library | 关键特性 | 帮助原因 |
|---|---|---|
| FlashList | 项目 回收 | 重用已渲染的项目,降低创建新项目的开销。 |
| LegendList | 响应式 与可选回收 | 当没有变化时防止项目重新渲染,消除空白。 |
| Legend‑State | 细粒度响应式 | 与 LegendList 配合使用,实现实时数据更新而无需不必要的重新渲染。 |
LegendList 是一种强大的解决方案,可高效渲染大量项,通过精确定位和可选的回收机制有效消除空白。将其与 Legend‑State 结合使用,可在需要细粒度响应式(例如实时数据流)的场景下提供实时数据更新且不会产生不必要的重新渲染。
初始启动时间

启动时间 是指您的应用在设备上加载并运行所需的时间。它包括在 RAM 中加载和执行 JavaScript 包。
如果您的应用随附了 臃肿的 JS 包,用户会感受到明显的延迟,导致沮丧。
减少包大小和启动时间的技巧
- 启用 Hermes(或其他 JS 引擎)以加快启动速度。
- 使用代码拆分(
import()语句)来懒加载屏幕。 - 移除未使用的依赖(
npm prune、yarn autoclean)。 - 启用 Metro 的
inlineRequires以推迟模块初始化。 - 压缩资源(图片、字体),并尽可能使用矢量图形。
- 使用
npx react-native-bundle-visualizer分析包,找出大型模块。

最后思考
性能优化是一个 迭代过程:
- 分析 → 确定瓶颈。
- 应用针对性修复(列表虚拟化、包体积缩减、原生分析)。
- 重新分析 以验证改进。
遵循上述步骤,你将交付一款在高端和中端设备上都运行流畅的 React Native 应用。祝编码愉快!
Bundle Size
- 使用 webpack‑bundle‑analyzer 等工具查看哪些部分在你的 bundle 中占比最大。
- 找出体积较大的第三方依赖,并用更轻量的替代方案替换它们。
注意: 与网页不同,React Native 不 开箱即支持完整的代码拆分(code‑splitting)。
- 你可以尝试使用 Repack 打包工具,它提供代码拆分支持(需要额外配置)。
最佳实践:
- 将媒体资源(图片、SVG 等)从 JavaScript bundle 中剥离。
- 将它们托管在远程服务器,并使用 expo‑image 等库进行缓存。
懒加载的幻觉
在构建 Huddle01 Meet 应用时,我们注意到 Android 设备上出现了明显的卡顿。原因是什么?一次性渲染 所有 底部弹窗组件。
解决方案
{showSheet && <BottomSheet />}
- 只渲染当前可见的弹窗。
- Android 设备(尤其是中低端机型)内存和 CPU 受限,条件渲染可以显著提升流畅度。
经验法则: 不要渲染一开始不可见的 UI。
这种技巧我称之为 “懒加载的幻觉”。 明智地使用它,并结合 Intersection Observer API(或其 React‑Native 等价实现),可以彻底避免挂载屏幕外的组件。
语法糖的取舍
- 避免仅提供语法糖的“花哨”JavaScript库。
- 记住:JS 占 React‑Native 应用运行时约 80 %,因此每增加一个库都会影响性能。
建议
- 倾向于使用自定义实现,而不是笨重的第三方包。
- 在低端 Android 设备上跳过 CSS‑in‑JS 库,除非它们真的很轻量(例如 react‑native‑unistyle)。
- 在添加任何依赖之前进行测量——运行时开销是性能的最大敌人。
不要为你的目标受众(例如 $100‑range 手机)永远不会使用的功能进行优化。
命令式 UI 更新
React 的声明式模型表现出色,但有时完整的重新渲染代价太高。
setNativeProps(link)允许你在不触发 React 渲染的情况下修改原生视图。- 谨慎使用它;它可能导致 React 状态与 UI 不同步。
**典型用例:**在低端设备上切换暗/亮模式。通过 React 状态更新整个 UI 可能会出现明显的卡顿;命令式更新可能更快,但必须手动保持 React 状态同步。
动画
- react‑native‑reanimated 将动画工作卸载到 UI 线程,这对高端设备非常有利。
- 在低端 Android 手机上,额外的线程开销可能适得其反,导致动画卡顿或无法运行。
指南
- 如果你的主要受众使用低端硬件,请坚持使用 vanilla React‑Native 动画(
AnimatedAPI),以减少线程争用。
Leveraging GPU Resources

- react‑native‑skia 让你直接在 JavaScript 中使用 GPU 绘制图形,实现实时图像处理和着色器效果。
- react‑native‑filament(由 Margelo 开发)在原生 GPU 上渲染完整的 3D 场景——想象一下 “Pokemon GO‑style” 的体验。
Why it matters: 将繁重的视觉工作卸载到 GPU 可以减轻 JavaScript 线程的压力,从而在资源受限的设备上实现更流畅的 UI。
C++ 魔法与新架构
React Native 的 新架构(TurboModules、Fabric、JSI)允许您使用 C++ 编写性能关键代码,并几乎零开销地将其暴露给 JavaScript。
- 使用 TurboModules 处理需要频繁调用的原生模块。
- 利用 JSI(JavaScript 接口)在 C++ 与 JS 之间桥接,避免桥接瓶颈。
结果: 更快的原生到 JS 通信,降低延迟,并更好地利用设备资源。
低端 Android 优化快速检查清单
| ✅ | 操作 |
|---|---|
| 1 | 分析 bundle 大小;剔除体积大的依赖。 |
| 2 | 将媒体资源托管在远程;使用 expo-image 进行缓存。 |
| 3 | 仅渲染可见组件(条件渲染、Intersection Observer)。 |
| 4 | 避免不必要的“语法糖”库;在添加前进行测量。 |
| 5 | 仅在能够保持 React 状态同步时使用 setNativeProps。 |
| 6 | 在低端设备上,优先使用原生 Animated API 而非 Reanimated。 |
| 7 | 使用 react-native-skia 或 react-native-filament 将图形卸载到 GPU。 |
| 8 | 采用新架构(TurboModules、Fabric、JSI)以实现 C++ 级别的性能。 |
React Native、JSI 与 C++ 的强大力量
JSI(JavaScript Interface) 消除了传统桥接的需求,使得可以直接从 JavaScript 运行时访问原生 API。它使用 C++ 编写,提供了一种高性能、低开销的调用原生代码的方式。
最有经验的 C++ 工程师之一、React Native 的核心贡献者 Marc Mrousavy 以及他的团队发布了多个强大的库,这些库利用了完全用 C++ 编写的 JSI 模块。
- react‑native‑quick‑crypto – 一个 C++ 实现,在原生端完成所有繁重工作,使 JavaScript 线程保持完全非阻塞。
- Nitro Modules – 一种使用高度优化的 JSI 编写原生模块的新方式,端到端类型安全。基准测试请查看 这里。
为什么 C++ 如今如此重要
得益于 AI 辅助开发,基于特定需求生成原生模块变得前所未有的容易。Nitro Modules 加速了这一过程,使原生代码的编写更快、更稳健。
原生代码与 JavaScript 之间的界限正在模糊。C++ 正是那座桥梁,让编写自定义原生实现变得直接,从而推动 React Native 能力的极限。
结论
过去五年是 React Native 的黄金时期。在社区的支持下,我们现在拥有了真正 “写一次,运行于任何平台” 的代码库。随着我们变得更加有创意,我们必须推动现有技术的极限。React Native 在某些领域仍可能存在限制,但它将继续改进。未来的继任者可能最终克服我们今天面临的挑战。看到像 React Native 和 Flutter 这样的跨平台技术不断演进,令人着迷。
感谢阅读本博客。欢迎在评论区提出任何问题。
新年快乐!