React Native 0.52でAndroidのリリースビルドを行った際に生成されるAPKファイルにindex.android.bundleが保存されず、実行できないという問題に直面しました。
いろいろ調べたところ、使っているReact NativeのバージョンのAndroidビルドに問題があることがわかったのでまとめました。
経緯
具体的にはAndroid用のリリースビルドを行うときには
$ cd android
$ ./gradlew assembleRelease
を実行し、app-release.apk
というAPKファイルを生成し、それを配布する、というのが通常の流れになります。
APKファイルにはReact Nativeのランタイムやアプリのリソース、そして、自分たちが書いたJavaScriptのコードがバンドルされます。
APKファイルの実態はZIPアーカイブなので、 unzip -l
などで中身を見ることができます。
$ unzip -l app-release.apk
問題はこの中に自分たちのJavaScriptが保存されなくなってしまったことです。
すべてはこいつ react.gradle
Androidはgradleというビルドツールを使ってビルドしており、React Nativeにおいてはfacebook/react-nativeのreact.gradle
というファイルに問題があったようです。
ざっくりいうと、react-native bundle
を実行し、自分が書いたJavaScriptのコードをindex.android.bundle
という1つのファイルにまとめてくれます。
いろいろ調べていると、どうもこのロジックが怪しい模様でした。調査結果から言うと、
試しに0.57のファイルを node_modules/react-native/
にコピーしたところ、無事にAPKに追加されるようになりました。
- 使っていたバージョン(0.52) https://github.com/facebook/react-native/blob/0.52-stable/react.gradle
- 最新バージョン(0.57) https://github.com/facebook/react-native/blob/0.57-stable/react.gradle
さらに深掘り
こちらの2つを比べると分かるのですが、index.android.bundle
の出力先が変更されていることがわかります。
- 0.52:
android/app/build/intermediates/assets/release
- 0.57:
android/app/build/generated/assets/react/release
GitHubのIssueなどを探してみたところ、やはりビルドのようにクリティカルな話だけあって、 かなり盛り上がっておりました。
最終的にはこのコメント に書いてあるのが最終的な修正のようです。一番キーのメッセージがこちら
Output to "build/generated" instead of "build/intermediates"
ただ、やはりビルド全体が複雑なのか、「何が」「いつから」「どう」「なんで」変わったのかは記載されておらず、自分たちの環境でも何故突然起きたのか分かりませんでした。
結論
とは言いつつも、node_modules/react-native/
の下のファイルを入れ替えたりするのは危なっかしいので、実際には別の回避策を設けておいて、React Nativeのバージョンアップを待つこととしました。
余談1: enableAapt2
AndroidのパッケージツールのAapt2ですが、こちらはReact Nativeと相性が悪く、だいたいgradle.properties
とかでenableAapt2=false
としてオフにすることになるのですが、上記の修正の一環としてビルドの順番とかを修正したおかげで、再び使えるようになりました!enableAapt2=true
、もしくは消してしまってもビルドできるようになります。
余談2: PRが出たり入ったり
ちなみ、facebook/react-native#17967で一度入ったのですが、revertされたらしく、最終的にはfacebook/react-native#20526になります(変更内容は同じのようです)。