📱

再訪 React Native

2024/11/19に公開5

最近React Nativeを使ってアプリを作る機会があり、React Nativeの進化に驚いたのでシェアします。

筆者のReact Native歴

  • 元々はAndroidとiOSでそれぞれネイティブアプリを作っていました。
  • 2017~2019年くらいに仕事と趣味の両方でReact Nativeを使っていました。
  • 2019年くらいからFlutterを使ってアプリ開発をするようになり、それ以降はFlutter or ネイティブ開発のみで、React Nativeは使わなくなりました。

当時(~2019)のReact Nativeの印象

5年以上前なので朧げな部分もあります。

  • 一つのソースコードでAndroidとiOSのアプリがどちらも作れて便利
  • パフォーマンスはネイティブほどではないが、ほとんどの画面で別に気にならない。アニメーションを大量に入れようとすると明らかにカクツク。
    • 当時はパフォーマンスのためにFlatlistを使った方がいいかもって言われ始めたくらいの時期
  • 公式のライブラリはあまり充実していないので、かなりたくさんサードパーティのライブラリを入れて使っていた。AirBnBあたりがよくOSSでライブラリを公開していた気がする(react-native-mapsなど)。
  • ビルドが壊れやすい。特にiOSのビルドがコケやすく、コケると大体半日くらいcocoapodsあたりのリンクを見直すことになる。
  • ライブラリの導入がややこしい。特にネイティブコードを利用する系のライブラリは、npmでjsのライブラリをインストールして、Xcodeを開いてnode_modules以下にある***.xcframeworkファイルをリンクして、Android Studioを開いて***.aarファイルをbuild.gradleファイルに追記してようやく使うことができた。
  • ↑のようにライブラリの導入が大変なので、各ライブラリのREADME.mdにあるInstallationセクションがやたら長い。
  • Expoは当時からあったし使われていた。ただネイティブコードを利用するライブラリは後から追加ができず、Expoに同梱されているものしか使えなかったので、結局ほとんどの場合npm run ejectして素のReact Nativeを使っていた。
  • react-native-webもあったけど、あくまでReact Nativeに似たWebのライブラリという印象だった。
  • react-native-web以外に、iOSのUIViewをJavascriptでエミュレートして、WebWorkerとかもフル活用しながらReact NativeをWeb上で動かす夢のようなプロジェクトがあった。react-native-guiみたいな名前だった気がするが、今検索しても全くヒットしなかったので本当に夢だったかもしれない。
  • Google PlayやApp Storeの審査をすっ飛ばしてJSのバンドルだけ配って更新するOTA Updateも当時から使えたが、Expo環境でしか使えないので結局使わずじまいだった。周りでもやっている人は見たことがなかった。
  • 後発のFlutterと比較されることが多かったが、Flutterはネイティブコードを含むライブラリの仕組みをPluginとしてサポートしていて、ライブラリ導入の簡単さが大きく違った。

現在(2024)のReact Nativeの印象

Expo一強になっている

React Native公式ドキュメントのガイドがExpoを前提にしたものになっているのに驚きました。一応React Nativeのみで行うセットアップも一応あるにはありますが、非推奨の注意文を読んだ先の奥まったところにポツンとリンクが置いてあるだけです。
ReactもNext.jsなどのフレームワークを前提としたガイドになっているので、これは最近の潮流なのかもしれません。

Expoにサードパーティのネイティブライブラリを入れられるようになっている

Continuous Native Generation (CNG)という仕組みによってAndroid、iOSのネイティブコードをプラグインとして読み込みながら、Expoの開発体験を維持できるようになりました。見たところほとんどのライブラリがすでにこれに対応していて、npmでインストールするだけで何もしなくても使えるようになっています。

AndroidとiOSのプロジェクトを全く触らずに開発ができる

Expoで作られるプロジェクトにはそもそもandroidiosといったディレクトリが存在せず、ネイティブのプロジェクトに関する設定は全く必要がありません。Xcodeプロジェクトの設定などは全てapp.jsonというファイル一つで行えるようになっています。
ネイティブコードのやり取りが小慣れていたFlutterでさえ、パーミッションの設定やCapabilitiesの追加などでネイティブのプロジェクトに手を入れる必要はあったので、それらもapp.jsonで完結するというのはすごいですね。

速くなった(らしい)

これは正直まだちゃんと検証できていないのですが、ランタイムのJSエンジンを独自のHermesに切り替えたり、JS <=> ネイティブコード間の通信を大幅に効率化したりしたおかげで、パフォーマンスが向上しているようです。こんなんいくら速くたっていいですからね。

OTA Updateが使いやすくなった

Expoが複雑な要件のアプリにも使えるようになったおかげで、OTA Updateを使うハードルがかなり下がりました。審査を含むリリースはどうしても時間がかかってしまいがちですが、OTA UpdateならWebサイトの公開と同じくらい簡単にリリースができるので、細かくリリースサイクルを回したいときや、急なバグ修正に対応するのに便利です。

デプロイが簡単になった

以前は単なるライブラリだったExpoですが、最近はEAS(Expo Application Services)というクラウドサービスを提供しているようです。EASはReact Native開発の色々な面倒ごとを一挙に引き受けてくれるサービスで、アプリのビルド、証明書の管理、審査への提出などをネイティブアプリ開発への知識をほとんど必要とせずにすることが可能です。

ExpoでWebのSPAが簡単に作れる

Expoのテンプレートにreact-native-webが含まれているので、Web向けのビルドコマンドを叩くだけで同等の機能のWebアプリを出力することができます。
SSRを含むフルスタックのWebアプリを作るまでとはいきませんが、Web向けに簡易的に公開できるだけでもいいのであれば選択肢の一つになりうると思います。

ベンダーロックイン感がある

Expoが便利になりすぎた裏返しではあるのですが、ドキュメントなどをみていてもExpoユーザー向けの説明になっていたり、Expoを使っていたらEASのコマンドを半ば強制的に使うことになったりと、ExpoとEASへの引力をかなり感じます。
ReactにおけるNext.jsやVercelの関係と似たようなもので、流れに従っている間はすごく快適なんですが、一度そこから外れてしまうとまとまったドキュメントが全然見つからないような状況になりそうです。

Expoが半公式になったことで信頼性の高いライブラリが増えた

以前のReact Nativeは公式が提供しているライブラリはごく一部で、個人がメンテナンスしているライブラリを多く使っていく印象でしたが、現在では基本的なアプリの機能はExpoが管理するライブラリとして提供されているため、メンテナンスの持続性に関する心配事が減りました。
こちらに利用可能なパッケージの一覧があります。

まとめ

一時期はFlutterの登場などもあって下火になったReact Nativeですが、久々に使ってみたら別物になっていてたまげました。ネイティブアプリ開発に関する知識がほとんど必要ないくらい進化しているので、チームメンバーの構成によっては今後有力な選択肢になってくると思います。

Discussion

JboyHashimotoJboyHashimoto

bun installだと早くインストールできるから快適になりますよ。参考までに
https://zenn.dev/joo_hashi/articles/3188d17ab33a88

JboyHashimotoJboyHashimoto

npm installだと遅くて😅
しかしまだ対応できないパッケージもあるかもです。ReactNativeに可能性を感じました。
TypeScriptだけ対応した外部サービスにも対応してるので可能性を感じますね。名前は忘れましたが😅
converx?
conbox?

mrtrymrtry

react-native-web以外に、iOSのUIViewをJavascriptでエミュレートして、WebWorkerとかもフル活用しながらReact NativeをWeb上で動かす夢のようなプロジェクトがあった。react-native-guiみたいな名前だった気がするが、今検索しても全くヒットしなかったので本当に夢だったかもしれない。

たぶん、react-native-domですかね?
https://github.com/vincentriemer/react-native-dom

こちらもぜひどうぞ
https://zenn.dev/nkzn/articles/diff-between-react-dom-and-react-native