加速你的构建阶段
构建你的 React Native 应用程序可能成本很高,并会占用开发者数分钟的时间。当你的项目增长时,尤其是在拥有多名 React Native 开发者的大型组织中,这可能会成为问题。
为了缓解这种性能影响,本页分享了一些关于如何提高你的构建时间的建议。
在开发期间仅构建一个 ABI (仅限 Android)
当在本地构建你的 Android 应用程序时,默认情况下你会构建所有 4 个 应用程序二进制接口 (ABI):armeabi-v7a
、arm64-v8a
、x86
& x86_64
。
但是,如果你在本地构建并在模拟器或物理设备上进行测试,你可能不需要构建所有这些。
这应该将你的 原生构建时间 减少约 75%。
如果你正在使用 React Native CLI,你可以将 --active-arch-only
标志添加到 run-android
命令中。此标志将确保从正在运行的模拟器或插入的手机中选择正确的 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,而不仅仅是适用于你在日常开发工作流程中使用的 ABI。
使用编译器缓存
如果你频繁运行原生构建(无论是 C++ 还是 Objective-C),你可能会从使用编译器缓存中受益。
具体来说,你可以使用两种类型的缓存:本地编译器缓存和分布式编译器缓存。
本地缓存
以下说明适用于 Android 和 iOS。如果你只构建 Android 应用程序,你应该可以顺利进行。如果你也构建 iOS 应用程序,请按照下面的 XCode 特定设置 部分中的说明进行操作。
我们建议使用 ccache 来缓存你的原生构建的编译。Ccache 的工作原理是包装 C++ 编译器,存储编译结果,并在最初存储了中间编译结果时跳过编译。
Ccache 在大多数操作系统的软件包管理器中都可用。在 macOS 上,我们可以使用 brew install ccache
安装 ccache。或者你可以按照 官方安装说明 从源代码安装。
然后你可以进行两次干净的构建(例如,在 Android 上,你可以首先运行 yarn react-native run-android
,删除 android/app/build
文件夹,然后再次运行第一个命令)。你会注意到第二次构建比第一次构建快得多(应该只需几秒钟而不是几分钟)。在构建时,你可以验证 ccache
是否正常工作,并检查缓存命中/未命中率 ccache -s
$ 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 上效果不佳,因为文件在每次 CI 运行时都会重新下载。为了克服这个问题,你需要使用compiler_check content
选项,该选项依赖于 哈希文件的内容。
分布式缓存
与本地缓存类似,你可能需要考虑为你的原生构建使用分布式缓存。这在频繁进行原生构建的大型组织中可能特别有用。
我们建议使用 sccache 来实现这一点。关于如何设置和使用此工具的说明,我们参考 sccache 分布式编译快速入门。