ビルドフェーズの高速化
React Nativeアプリのビルドはコストがかかり、開発者の時間が数分かかる場合があります。これは、プロジェクトが成長するにつれて、また一般的に複数のReact Native開発者がいる大規模な組織では問題になる可能性があります。
このパフォーマンスの低下を軽減するために、このページではビルド時間を改善する方法に関するいくつかの提案を紹介します。
開発中に1つのABIのみをビルドする(Androidのみ)
Androidアプリをローカルでビルドする場合、デフォルトでは4つのApplication Binary Interfaces (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プロパティに依存しています。
したがって、CLIを使用せずに、コマンドラインからGradleで直接ビルドする場合は、次のようにビルドする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バンドルをビルドする必要があるため、これらのフラグを削除することを忘れないでください。
コンパイラキャッシュを使用する
頻繁にネイティブビルド(C++またはObjective-C)を実行している場合は、コンパイラキャッシュを使用するとメリットがある可能性があります。
具体的には、ローカルコンパイラキャッシュと分散コンパイラキャッシュの2種類のキャッシュを使用できます。
ローカルキャッシュ
次の手順は、AndroidとiOSの両方で機能します。Androidアプリのみをビルドする場合は、問題ありません。iOSアプリもビルドする場合は、以下のXCode固有の設定セクションの手順に従ってください。
ネイティブビルドのコンパイルをキャッシュするには、ccacheを使用することをお勧めします。Ccacheは、C++コンパイラをラップし、コンパイル結果を保存し、中間コンパイル結果が最初に保存された場合はコンパイルをスキップすることで機能します。
Ccacheは、ほとんどのオペレーティングシステムのパッケージマネージャーで利用できます。macOSでは、brew install ccache
でccacheをインストールできます。または、公式インストール手順に従って、ソースからインストールすることもできます。
次に、2回のクリーンビルドを実行できます(たとえば、Androidでは最初にyarn react-native run-android
を実行し、android/app/build
フォルダーを削除して、もう一度最初のコマンドを実行できます)。2回目のビルドが1回目よりもはるかに速いことに気付くでしょう(数分ではなく数秒かかるはずです)。ビルド中に、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の分散コンパイルクイックスタートを参照してください。