普段Flutterを触ってる人がReact Native(+Expo)を触ってみた 2024/12
普段はFlutterでモバイルアプリ開発をやっているKurogoma4Dですが、最近技術スタックがFlutter OTP[1] みたいになってきているのを感じてます。
会社所属のエンジニアとしても個人のスキルとしても他の技術に触れなさすぎるのも良くない、というのと、最近 React Native と Expo を使ったアプリがパフォーマンスも改善されてるし結構いい感じらしい、という噂を聞いたということで、React Native(以下RNと略す)をちょっと触ってみました。
やったこと
まずはExpoの公式ドキュメントにある Expo Tutorial を一通りやってみました。
その後、自分で使いたいアプリを一個作ってみました。
画像を登録して、アプリ起動時に設定してある生体認証をクリアしたときのみ内容が見える、というものです。
具体的に何に使うんですか?ってツッコミは一旦しないでください。
RN+Expoを触って良かったこと
TypeScriptで書くのでベースのDXが良い
(DX: Developer Experience)
普段からVS Codeを使っているので、TypeScriptを書く環境が整っている(or すぐ整えられる)状態で開発が始められるのはいいですね。
AndroidやiOS向けのアプリをビルドする際は最終的にAndroid Studio、Xcodeが必要になりますが(EASを使う場合を除く)、Flutterと同じで大方の開発はVS Code上で完結します。
TypeScriptはVS Code上での補完やAIアシストが充実しているので、困ったことがあってもエディタ上で完結することは多いです。
(まぁ、Dartでもその辺の体験は良いですけどね🤫)
一回ビルドしたらHMRでスムーズに開発できる
これもFlutterで言うHot-reloadに通じる話ですが、やっぱりHMR(Hot Module Replacement)は偉大です。
参考文献として、RNの公式ブログとwebpack本家のドキュメントを置いておきます。HMRとは何ぞや、となっている方は以下をご覧ください。
ネイティブのViewになるので、各種inspectorでViewの様子が見られる
XcodeのinspectorでViewを見ている図
Viewとして描画したものが最終的にどういうconstraintsになっているか、みたいな確認をしたいときには便利かと思います。
Reactの世界でどうなってるか、を見たければ別途それ用のDevToolもあります。
react-native-reanimatedが結構便利
Flutterで言うAnimated系Widgetのようなお手軽さで、アプリにアニメーションを導入することができます。
function App() {
const width = useSharedValue(100);
const handlePress = () => {
width.value = withSpring(width.value + 50);
};
return <Animated.View style={{ ...styles.box, width }} />
}
こんな感じ↑のコードで、こんな感じ↓の出力が得られます。超お手軽。
react-native-reanimatedの例 https://docs.swmansion.com/react-native-reanimated/
Androidでビルド時の様子がだいぶ可視化されてておもろい
こんな感じ
アイコンとかの設定がめっちゃ楽
アプリ名とかアイコンとか、通常 AndroidManifest.xml
なり Info.plist
なり違うサイズのアセットを自前で用意するなり、ネイティブの開発では色々と設定が大変な部分があります。
Expoでは、app.json
を編集して npx expo prebuild:android
を叩けば大抵の設定は完了するのでめっちゃ楽です。
環境分けに関してはちゃんと調べてないですが🤫
Flutterでもアイコンなら例えば flutter_launcher_icons を使えば楽できます。アプリ名はよくネイティブいじりますがね……
RN+Expoを触ってイマイチだったこと
「一回ビルドしたらHMRでスムーズに開発できる」のデメリット
これはイマイチと言うかある程度仕方ない部分ではありますが、Flutterでは感じることのないデメリットがあるな、と思いました。
RNでは Native module に変更がない限りは基本的にdevサーバーを立ち上げるだけで開発ができますが、逆に変更があった場合はビルドし直さなければなりません。
その際、コマンドとしてはnpx expo start
ではなく npx expo run:android
や npx expo run:ios
といったコマンドを使うことになります。
Native module に変更があるにもかかわらず、誤って npx expo start
だけしてしまった場合、往々にしてランタイムエラーが起こります( Error: Native module not found
的なやつ)。
こう言うと当然の話ではありますが、自分が何をしようとしているのか・何をしたのかは常に把握しておきましょう。
ビルド自体の時間もなにもない状態にもかかわらずネイティブアプリと比べると段違いに遅い
場合によりけりですが、ビルドの時間がめっちゃ遅いときがあります。
おそらくJSの実行環境が入ってたり諸々必要なものが多い関係かと思われます。
ライブラリの追加など Native module に変更があったとしてもビルドが早かったりそうでもなかったりマチマチなので、流石にキャッシュ等で最適化はされているもののどれくらいビルドに時間がかかるか、はやってみないとわからない印象でした。
Flutterで言うWrap with widgetがなくてぐぬぬ…ってなる
どっちかって言うとReact単体の話にはなりますが、コンポーネントを組み立てるときに便利なCode Actionsが無いなぁという話です。
これ
FlutterではWidgetを組み立てる際、↑の画像のようなCode ActionsをWidget上で呼び出すことで、カーソル位置のWidgetをラップしたり削除したり、という記述が簡単にできます。
これと同じものがReactでほしい……😫
普段Reactを書いている友人にどうしているか聞いてみたところ、普通に中身をカットしてタグ書いて中にペーストしてるそうで、「あまり気にしたことない」とのことでした。
作ろうと思えば作れるかなこれ🤔
総評
実際にRN+Expoでアプリを作ってみて、特に大きな問題もなく開発体験もパフォーマンスも悪くないな、というのが第一の感想です。大手企業のアプリで採用されていることもあり、クロスプラットフォームで開発したいときの選択肢には余裕で入ってくるかと思います。
ネイティブUIのレンダリングをする系のフレームワークだとUIの自由度が低いんじゃないか[2]、と勝手に思ってましたが、全然そんなこともなく、Webと同じようにCSS的なものでカスタマイズが自由にできるしアニメーションも手軽にできることがわかりました(FlutterのAnimationControllerみたいに原理的なAPIを使うところまでは調べてないので、あくまで所感)。
FlutterとRNを比較したときに考える点としては今のところ以下があるかなと思いました。
- Android/iOS/Web以外のプラットフォームを考慮するかどうか
- 各種デスクトップはFlutterのほうが楽に組み込める(と思う)
- プロトタイプ的な開発(PoC)かどうか
- PoC的なものをスピード感持って作るなら、UIの自由度が高いFlutterのほうがやりやすい印象
- リリースに向けて改めて検討するのはありだと思う(言語が違うのでそれなりにコストはかかるが、もし余裕があれば)
Discussion