Expo bare workflowでの開発を1年ほどやってみてよかったこと・悪かったこと

※先日空き枠があったので登録してみたものの、すっかり忘れており遅くなりすみません、、
React Native Advent Calendar 2020の9日目の記事になるはずだったものです。


# はじめに
昨年のAdvent Calendarでは[2019年Expoで辛かったことベスト5](https://qiita.com/muzou/items/f50a6dca3aa3a8f53695)という内容で投稿したのですが、
その後Expoでは従来のmanaged workflowとexpoからのeject(ExpoKit利用)に変わり、bare workflowという選択肢が公式に追加されました。

ExpoのApiを生ReactNativeのプロジェクトでも使用できるように、という流れは2019の半ばからreact-native-unimodulesという形で紹介され、道半ばではあったのですが、expo SDK37のリリース(とexpoKit廃止）を持ってそれが公式?に完了した形になるのかなと思っています。

参考1: 
https://blog.expo.io/you-can-now-use-expo-apis-in-any-react-native-app-7c3a93041331

参考2:
https://dev.to/expo/time-to-start-using-expo-s-bare-workflow-expokit-is-now-deprecated-51ih

Expoの各種APIの便利さ、xcodeを立ち上げることなく開発できることの手軽さに魅了されていながらも、細かいところの改修やデバッグの辛さを感じていたこともあり、2月ごろに開始の案件からbare workfowでの開発を試し始めました。

この記事ではその中で感じたメリット・デメリットの一部を紹介できればと思います。


# よかったこと
## Native Moduleを含むライブラリが使える
なんにせよこれに尽きるのですが、使用可能なライブラリに制限がないのがありがたいです。
特にreact-native-firebase入れられるのはありがたい、、！

## Expoで開発していた時の知見も、生ReactNativeで開発していた時の知見もどちらも使える
弊社では、2019年はExpoメイン、それまではプレーンなReactNativeがメインで開発をしており、それぞれで利用したことがあるAPIやライブラリがある状況でした。
ExpoのライブラリもおそらくベースとなるOSSがあるものが多い印象で、大枠の使い方は同じだったりするのですが、微妙な差分があったり細かいところが違ったりという感じで、「ExpoのXXXだったら。。」だったり、逆に「react-native-XXXだったら。。」と痒い所に手が届かない思いをすることもありました。
bare workflowでは、その時々に応じて必要な選択をとれるので、今までのreact-native経験を生かせるような印象を受けました。

## expoのapiのネイティブコードもデバッグできる
managed workflowで開発していたときにで、expoで意図しない挙動があった際、ネイティブ側でどのような処理がされているのかわからなく、つらかったことがあるのですが、bare workflowなら手元でビルドできるの確認が楽です。


# つらかったこと
## 環境ごとのビルドの設定負荷は生react-nativeと一緒
managed workflowだとビルド、credentialの管理provisioning profileの管理等、expoサーバー側でやってくれることも多く、コマンド一つでビルド、アップロードとできたのですが、bare workflowだとこの辺りは通常のreact-nativeアプリと同様です。
とはいえ↓を見ると use expo build server がin progressになっているので今後に期待です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206623/250dc63e-c5ca-5eb3-aebe-71de44177ccd.png)

https://docs.expo.io/introduction/managed-vs-bare/

## expo-updatesがなかなかに使いづらい
managed workflowの場合、ほぼほぼの設定がjsレイヤーで完結するため、OTA配信の際の互換性等をそこまで考えなくても(expo sdkやapp.jsonでネイティブの設定が変わらない限り)よかったのですが、bare workflowでネイティブライブラリをつかっている場合、ビルドごとのOTAリリース管理をしっかりしないといけません。

expoのOTAアップデートの際にはreleseChannelを指定することにより、同じchannelのみに配信することができるのですが、これを利用し `staging-v1.0.0`や`production-v1.2.0`のようにチャンネルをしていることでカバーすることは可能です。

ただし厄介なのは、publishした際にネイティブ側で読み込むExpo.plistやbundleされたコードなどが生成されるため、複数のschemaやtargetをつかって環境を管理している場合この辺りの管理が煩雑になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206623/7ef2f03c-9cf4-3073-cade-0cddb321db9c.png)

そして、publishのタイミングで自動生成され書き換わるものもあり、どのタイミングで何が変わるのかを理解しておかないと事故が発生します。
たとえば、stg確認用にstgのチャンネルでpublishした後、本番ビルドをつくったりすると、適切に分離されていないとExpo.plistがstg向きのものを参照してしまう、といったことが起こりうります。

自分の場合はsupportingファイル自体を別に出力できるようにapp.jsonを分け、build phaseにスクリプトを追加して、対象のものが選ばれるようにコピーしたりするようにしたりしていました。

が、
この辺りがいやだったので、結局、案件によってはcodepushに載せ替えたりしました。
（この辺についてはexpo37のときの経験なので、最新版だと変更されているかもしれません、、そしてもっといい方法もあるような気もしています。未確認）


# その他
 - 自分の場合はつかっていないですが、expoのクライアントアプリでもbareワークフローのアプリを起動できるようなので、nativeのライブラリが少ない場合は確認早くていいかもしれないです。
 - そもそもbare workflowではなくてunimoduleだけでもいいのではないか、説もありますが、、一応expoベースのコード多いので自分はbare workflowを使用しました。

# まとめ
auto linking等、RN自体がnative moduleをつかってもストレス少ないように改善されてきていることもあり、今の心情的にはmanaged workflowよりもbare workflowもしくはそのままのreact-nativeを使うことが今後多くなりそうです。