加快构建阶段
构建您的 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 而不仅仅是您日常开发工作流中使用的 ABI 的 apk/app bundle。
启用配置缓存(仅限 Android)
自 React Native 0.79 起,您还可以启用 Gradle 配置缓存。
当您使用 yarn android
运行 Android 构建时,您将执行一个由两个步骤组成的 Gradle 构建(来源):
- 配置阶段,评估所有
.gradle
文件。 - 执行阶段,实际执行任务,编译 Java/Kotlin 代码等。
您现在可以启用配置缓存,这将允许您在后续构建中跳过配置阶段。
这在频繁更改原生代码时很有益,因为它可以缩短构建时间。
例如,您可以看到在原生代码更改后如何更快地重新构建 RN-Tester:
您可以通过在 android/gradle.properties
文件中添加以下行来启用 Gradle 配置缓存:
org.gradle.configuration-cache=true
有关配置缓存的更多资源,请参阅官方 Gradle 文档。
使用 Maven 镜像(仅限 Android)
构建 Android 应用时,您的 Gradle 构建将需要从 Maven Central 和互联网上的其他仓库下载必要的依赖项。
如果您的组织正在运行 Maven 仓库镜像,您应该考虑使用它,因为它将通过从镜像而不是从互联网下载工件来加速您的构建。
您可以通过在 android/gradle.properties
文件中指定 exclusiveEnterpriseRepository
属性来配置镜像:
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
# Use this property to configure a Maven enterprise repository
# that will be used exclusively to fetch all of your dependencies.
+exclusiveEnterpriseRepository=https://my.internal.proxy.net/
通过设置此属性,您的构建将仅从您指定的仓库而不是其他仓库获取依赖项。
使用编译器缓存
如果您经常运行原生构建(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
中为 ccache 启用 React Native 支持。
在编辑器中打开 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 的分布式编译快速入门以获取有关如何设置和使用此工具的说明。