优化构建阶段速度
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
构建 React Native 应用可能会非常耗时,每次构建都会占用开发者数分钟的时间。当项目规模增长时,或是在拥有多名 React Native 开发者的大型组织中,这个问题会变得尤为突出。
为了缓解这一性能瓶颈,本文将分享几种优化构建时间的有效方法。
开发阶段仅构建一种 ABI(仅限 Android)
在本地构建 Android 应用时,默认会编译全部 4 种 应用二进制接口(ABI):armeabi-v7a、arm64-v8a、x86 和 x86_64。
但如果你只是在本地构建并在模拟器或物理设备上测试,通常不需要编译所有架构。
这种优化可以将原生构建时间减少约 75%。
如果使用 React Native CLI,可以在 run-android 命令后添加 --active-arch-only 标志。该标志会从正在运行的模拟器或已连接的设备自动选择正确的 ABI。验证方法:在控制台看到类似 info Detected architectures arm64-v8a 的信息即表示生效。
$ yarn react-native run-android --active-arch-only
[ ... ]
info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
Jetifier found 1037 file(s) to forward-jetify. Using 32 workers...
info JS server already running.
info Detected architectures arm64-v8a
info Installing the app...
该机制依赖于 reactNativeArchitectures 这个 Gradle 属性。
因此,如果直接通过命令行使用 Gradle 构建(不通过 CLI),可以按以下方式指定要构建的 ABI:
$ ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86,x86_64
这在 CI 上构建 Android 应用时特别有用,你可以通过矩阵并行化编译不同架构。
如需在本地覆盖该值,可以修改项目顶层目录中的 gradle.properties 文件:
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
构建正式发布版本时,请务必移除这些标志,因为你需要生成支持所有 ABI 的 apk/app bundle,而不仅仅是日常开发使用的单一架构。
使用编译器缓存
如果需要频繁进行原生构建(C++ 或 Objective-C),使用编译器缓存会带来显著收益。
具体有两种缓存类型可用:本地编译器缓存和分布式编译器缓存。
本地缓存
以下说明适用于 Android 和 iOS:
- 如果仅构建 Android 应用,可直接使用本方案
- 如果同时构建 iOS 应用,请额外遵循下方 Xcode 专属设置 的说明
建议使用 ccache 缓存原生构建的编译结果。它的工作原理是封装 C++ 编译器:存储编译结果,当遇到相同中间文件时直接跳过编译过程。
ccache 可通过主流操作系统包管理器安装。在 macOS 上可运行 brew install ccache,或参考官方安装说明从源码编译。
你可以执行两次全新构建验证效果(例如在 Android 项目:先运行 yarn react-native run-android,删除 android/app/build 目录后再次运行)。第二次构建速度会明显提升(耗时从分钟级降至秒级)。构建过程中可通过 ccache -s 查看缓存命中率,验证 ccache 是否正常工作。
$ ccache -s
Summary:
Hits: 196 / 3068 (6.39 %)
Direct: 0 / 3068 (0.00 %)
Preprocessed: 196 / 3068 (6.39 %)
Misses: 2872
Direct: 3068
Preprocessed: 2872
Uncacheable: 1
Primary storage:
Hits: 196 / 6136 (3.19 %)
Misses: 5940
Cache size (GB): 0.60 / 20.00 (3.00 %)
注意,ccache 会累计所有构建的统计信息。你可以在构建前使用 ccache --zero-stats 重置统计信息,以验证缓存命中率。
如需清除缓存,可使用 ccache --clear 命令。
Xcode 特定设置
为确保 ccache 在 iOS 和 Xcode 中正常工作,你需要在 ios/Podfile 文件中启用 React Native 对 ccache 的支持。
在编辑器中打开 ios/Podfile 文件,并取消注释 ccache_enabled 这一行。
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# TODO: Uncomment the line below
:ccache_enabled => true
)
end
在 CI 上使用此方法
Ccache 在 macOS 上使用 /Users/$USER/Library/Caches/ccache 目录存储缓存。因此你也可以在 CI 上保存并恢复该目录来加速构建。
但需要注意以下几点:
-
在 CI 上,我们建议进行完全干净的构建以避免缓存污染问题。如果采用前文提到的并行构建方法(在 4 个不同 ABI 上构建),CI 上很可能不需要使用
ccache。 -
ccache依赖时间戳计算缓存命中,这在 CI 环境下效果不佳(每次运行都会重新下载文件)。解决方法是通过compiler_check content选项改用文件内容哈希机制。
分布式缓存
除本地缓存外,你还可以考虑为原生构建配置分布式缓存。这在频繁进行原生构建的大型组织中特别有用。
我们推荐使用 sccache 实现此功能。具体设置方法请参考 sccache 的分布式编译快速入门指南。