🥺

ここがつらいよReact Native

に公開

こんにちは!テラーノベルとテラードラマでiOS/Android/Webとフロントエンド周りを担当している @kazutoyoです!

ここ数年、React Nativeに触れており、その開発体験や効率の良さに感動しています。
しかし、どんな技術でもいい面と悪い面はあり、普段はいいと思っている部分を共有していますが、今回私が実際に直面した辛いポイントを共有しようと思います。

1. React Native(Expo)のバージョンアップが大変

iOSやAndroidのネイティブの開発であれば、OSなどのメジャーアップデートは年に1度で、その基本的にタイミングでの対応をしておけば、それほどメンテナンスコストがかからず運用できるかと思います。

例えばExpoを利用する場合、年に3度ほどのメジャーバージョンが上がります。
また、Expoは基本的に最新バージョンから数えて4バージョン程度がサポート対象となります。
そのため、1年半以上放置しているとサポート対象が切られますし、そこからアップデートするにしても、3〜4バージョン分の差分があるため修正や検証のコストが大きく感じます。

基本的にはこまめにExpoの最新版に追従していくしかないのかなと考えています。
プロジェクトをCNGに対応してアップグレードをしやすくし、最新版に追従できるようにしていきましょう。

2. ライブラリの互換性

1.とも関連しますが、React NativeやExpo、またサードパーティのライブラリなどで、それぞれの依存関係の解決が面倒になることがあります。
ExpoではExpo CLIのexpo installコマンドを提供しており、それを用いることで互換性のあるバージョンを自動的に選択してくれます。
https://docs.expo.dev/more/expo-cli/#install

しかし、すべてのライブラリが対応しているわけではなく、また一部のライブラリでバージョンを指定したい場合などもあると思います。
そのようなときのバージョンの解決に時間を溶かすことがあります。

また、このように依存関係でバージョンを変更できない場合、最終的にパッチなどを当てて対応する必要が出てきます。
Blueskyのsocial-appリポジトリでも、多くのパッチが存在します。
https://github.com/bluesky-social/social-app/tree/main/patches

3. iOSのビルド時間が長い

React NativeのiOSのビルド時間は、マシンによっては数分程度かかることがあります。
これは、React Nativeのコード全体とその依存関係をすべてコンパイルする必要があるためです。

ただ、これから登場するReact Native 0.81では、React Nativeと周辺のライブラリをプリコンパイルすることにより、React Native自体のコンパイル時間が短縮され、場合によっては1/10にも短縮される可能性があるようです。
https://expo.dev/blog/precompiled-react-native-for-ios

また、Expo 53移行でビルドキャッシュの共有できるAPIが追加されました。
これらなども活用することで、ビルド時間を短縮できそうです。
https://expo.dev/blog/build-cache-providers-in-expo

4. CNG対応のためのConfig Pluginsの実装が面倒

CNGに対応することで、ネイティブのプロジェクトをコードで管理してクリーンに保つことができます。
ただし、ネイティブのプロジェクトに変更を加えたいときにはConfig Pluginsを実装する必要があります。

同じくBlueskyのsocial-appリポジトリでも、ネイティブプロジェクトの変更などのため、いくつかConfig Pluginsが作られています。(筆者はこちらをよく参考にして実装しています)
https://github.com/bluesky-social/social-app/tree/main/plugins

CNGとConfig Pluginsについての詳細はこちらもご参照ください。
https://zenn.dev/tellernovel_inc/articles/151fbb8fe6cdbe

5. 各プラットフォームの調整が必要

Flutterであればどのプラットフォームにおいても、Flutterのレンダリングエンジンによって同じように表示されると思います。
React Nativeの場合、プラットフォームごとのUIを利用することが可能であるため、場合によってはFlutterよりも調整コストが増える場合があります。

React Nativeは内部的にネイティブのViewが使われることによって、ネイティブと同じような体験を得ることがメリットではありますが、こういった点は考慮する必要がありそうです。

プラットフォームごとに実装を分ける場合、以下のリンクが参考になります。
https://reactnative.dev/docs/platform-specific-code

6. 既存のアプリの一部にReact Nativeを組み込むのは大変

こちらのドキュメントにあるように、既存のアプリにReact Nativeを組み込むことは可能です。
https://reactnative.dev/docs/integration-with-existing-apps

弊社のテラーノベルのアプリにおいても、エディタ機能に関してReact Nativeを組み込んで実現しています。

しかし、いくつかハマりポイントがあり、運用がとても大変だと感じています。

  • React NativeやExpoで使われているパッケージで、ネイティブのプロジェクトのパスがハードコードされていてパスが解決できないことがある
    • ネイティブプロジェクトのディレクトリ構造が ios/android/ で固定されていることがあり、そのような場合にパッチを当ててネイティブのプロジェクトのパスを修正する必要がある
  • ネイティブ側で利用しているライブラリと、React Nativeのライブラリで利用しているライブラリのバージョンを合わせる必要がある
    • たとえばFirebaseをNativeとReact Nativeの両方で使うとき、Nativeで指定しているバージョンを意識して、React Native Firebaseのバージョンを指定する必要がある
  • React Native(Expo)のバージョンアップも大変
    • CNGは利用できなく、React Nativeを利用するためのネイティブ側の設定は自分で管理する必要があるため、バージョンアップでReact Nativeの設定方法などが変わったときに、変更を把握しながら追従する必要がある

React Native Brownfieldを使うことで多少組み込みが簡単になるかも?
https://github.com/callstack/react-native-brownfield

まとめ

これらのように、私が数年ほどReact Nativeのアプリケーションを運用して"つらい"ところを共有してみました。

このような"つらい"部分は、近年React NativeやExpoなどが日々改善しているため、今後、こういった部分も次第に解消していくのではないかと考えています。

私自身、辛い部分を感じつつも、React Nativeの開発体験の良さやスピード感は非常に素晴らしいと思っているので、今後もReact Nativeを活用していきたいなと思います!

それでは良いReact Nativeライフを!

その他React Nativeの記事

https://zenn.dev/tellernovel_inc/articles/cdec85f50c8442

https://zenn.dev/tellernovel_inc/articles/5623475a2c6843

テラーノベル テックブログ

Discussion