🚀

Expo53にしてからネイティブコードにパッチが当たらない?それ解決できますよ!

に公開

はじめに

みなさん、Expoしてますか?(挨拶)

ライブラリ側起因の修正にパッチを使うことは、この界隈ではときおり発生します。
有名どころだと patch-package などを活用したりするんでしょうか。
yarn berryを使っているならyarn組み込みのパッチメカニズムを使えますし、様々なパッケージマネージャー内に組み込まれていることがあったりします。

Expoでアプリ開発をしていても例外ではなく、パッチを当てる機会はそこそこありますが、
Expoで使用するnpmパッケージのなかには、iOSやAndroidのネイティブコード、まぁつまりSwiftとかKotlinのソースコードにパッチを当てることも稀にあります。
今回筆者が遭遇したトラブルは、そういったネイティブコードへのパッチに関するものなのですが、なかなか興味深かったので記事にすることとします。

なんどビルドしなおしても、ネイティブコードに修正が反映されない!

私が開発しているプロジェクトでは、 expo-camera を使っています。

Expo52でexpo-cameraのネイティブコードにパッチを当て、無事に動作する状態でした。

今回、Expo53にアップグレードし、アプリを実際に起動させたところ、そのパッチが適用されない状態になってしまいました。。。
パッチの再作成を試しても効果が無いうえに、 node_modules にあるコードにもちゃんとパッチが当たった状態になっています。。。
だけど、実行したアプリはパッチが当たってない状態になってしまいました。。。
(JavaScript側にもパッチ適用していましたが、そっちは問題なくパッチが適用されていました)

いろいろ考えたり調べた結果、どうやら expo-camera 等の一部パッケージは "Prebuilt Expo Modules" という、ネイティブコードを事前ビルドしたものを別途使用していることが分かりました。

Expo53から導入された「Prebuilt Expo Modules for Android」とは?

https://docs.expo.dev/guides/prebuilt-expo-modules/

↑の資料を読むとすべて謎が解けるのですが、ある程度抜粋して書くと。。。

Prebuilt Expo Modulesは、Expo53から導入されたメカニズムで、Androidアプリのビルド時間を最大25%削減できます。

ビルドプロセス中に、パッケージ名の横に 📦 の絵文字が表示されることで、プリコンパイルされたバージョンが使用されていることがわかります。

特別な設定は不要で使えるようになります。逆に言うと、何もしなければ自動的に有効になるので、結果として、ネイティブコードへのパッチが適用されない状態になってしまいました。

解決方法

これも↑の記事に書いてあるのですが、 package.json に、Prebuild Moduleを適用したくないパッケージを記述するとOKです。

{
  "name": "your-app-name",
  "expo": {
    "autolinking": {
      "android": {
        "buildFromSource": [
          "expo-camera"
        ]
      }
    }
  }
}

正規表現が使えるので、Prebuild Moduleを使いたくなければ buildFromSource".*" を記述するとOKです。

おわりに

最近のExpoはビルド高速化のために、iOSやAndroidのビルドの最適化をいろいろと行っています。
それ自体は非常に良いことではあるのですが、プロジェクトでちょっと特殊なことをしていたりするとハマることがあるので、
アップデートの時はちゃんとChangelogを確認して臨みたいところですね!

Discussion