🤡

yarn workspace環境でjetifyを実行する場所はrootが良いかもしれない

2022/02/01に公開

lerna -> yarn workspace へ

lerna から yarn workspace にモノレポ管理するツールを移行しつつ、古いアーキテクチャを刷新しています。

その中で lerna がデフォルトで有効になっていない yarn workspace の hoist 機能が使われるようになったため、 npm モジュールが格納される node_modules のディレクトリが、

子 package の node_modules -> ルートの node_modules

に巻き上げされました。

lerna でも hoist は使えるようですが、ちょっと条件があります。

https://github.com/lerna/lerna/blob/main/doc/hoist.md

何が起こったか

yarn workspace の hoist 機能により、 React Native 関連のパスが子 package のディレクトリからルートディレクトリに変更しないといけなかったりします。

そのあたりは、かむかむレモンさんの記事が詳しいです。

https://zenn.dev/camcam_lemon/articles/0b4ac3a54675e59b4757

そしてここで一つ問題になってくるのが、いままで

npx jetify

を実行していたとすると、それはもしかすると子 package のディレクトリではなくルートディレクトリにしないとうまくいかないかもしれません。

ルートディレクトリに巻き上げされたからです。

npx jetify

https://github.com/mikehardy/jetifier

npx jetify の実行される場所について書きましたが、 React Native v0.60 以降だと react-native-community/cli で自動的にカレントディレクトリで実行されるようです。

ただし、これは yarn workspace を使ってる使っていないを考慮していません。

つまり、本当はルートディレクトリで実行しないと AndroidX 対応した React Native モジュールに変換 されないことを意味しています。

jetifyしないとどんなエラーが出るか

今回発生したエラーが出たのは

"react-native-firebase": "^5.6.0"

です。

以下のような Java のビルドエラーが出ました。

  シンボル:   クラス RemoteInput
  場所: クラス DisplayNotificationTask
/Users/project/node_modules/react-native-firebase/android/src/main/java/io/invertase/firebase/notifications/DisplayNotificationTask.java:501: エラー: パッケージRemoteInputは存在しません
    RemoteInput.Builder rb = new RemoteInput.Builder(resultKey);
               ^
/Users/project/node_modules/react-native-firebase/android/src/main/java/io/invertase/firebase/notifications/DisplayNotificationTask.java:501: エラー: パッケージRemoteInputは存在しません
    RemoteInput.Builder rb = new RemoteInput.Builder(resultKey);
                                            ^
注意:一部の入力ファイルは推奨されないAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
注意:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。
注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
エラー47個

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native-firebase:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1m 51s

    at makeError (/Users/project/node_modules/execa/index.js:174:9)
    at /Users/project/node_modules/execa/index.js:278:16
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async runOnAllDevices (/Users/project/node_modules/@react-native-community/cli-platform-android/build/commands/runAndroid/runOnAllDevices.js:94:5)
    at async Command.handleAction (/Users/project/node_modules/@react-native-community/cli/build/index.js:186:9)
info Run CLI with --verbose flag for more details.
error Command failed with exit code 1.

  シンボル:   クラス RequiresApi
  場所: クラス RNFirebaseNotificationManager
/Users/project/node_modules/react-native-firebase/android/src/main/java/io/invertase/firebase/notifications/RNFirebaseNotificationManager.java:398: エラー: シンボルを見つけられません
  @RequiresApi(api = 26)

これは lerna 時代には出なかったので、ハマるポイントだったのですが、 yarn workspace の巻き上げによって npx jetify が子 package で意味をなさず、結果的にコードの最適化がされなかったので yarn android でエラーが出たと。

ということでルートの package.json に、

"postinstall": "npx jetify"

を script として追加しました。

結果うまく yarn android されるようになりました。

さいごに

モノレポで React Native を使う構成のサンプル

https://github.com/hisasann/yarn-workspace-reactnative

最新の環境で、環境構築をすると思いの外苦労せずに動いてしまいます。

それが、ちょっとレガシーなシステムを最新ぽくすると、どっか微妙なところの設定などで動かなくなったりします。

今回のような Java コードの最適化がうまく動いていなかった系は、フロントエンドの領域外っぽさがあり調べる優先度が下がってしまうので、故にハマるポイントでもありました。

以下が今回の記事のポイントになります。

同じようなことで困っている方の参考になれば幸いです。

https://github.com/hisasann/yarn-workspace-reactnative/blob/main/package.json#L5

Discussion