Reactエンジニア向け:Reactアプリを2ヶ月でFlutterに移植した話
時間がない方向け/TL;DR
- Reactエンジニアがネイティブアプリを開発したいときはFlutter試してみるとよいよ
- Flutterの開発はReactと同じような開発体験でサクサク開発できます
- Riverpod + flutter_hooks便利!!!
はじめに
この1月末に、ReactとPWAを使用して開発したアプリをリリースしました。その後、このアプリをFlutterに移植し、再リリースした経験から得られた知見を共有します。
「日々のログ」とは?
「日々のログ」は、個人向けのデータベース兼ライフログアプリです。ユーザーは自由にテーブル(記録帳)を定義し、日常のデータを気軽に迅速に入力できます。
例えば、投薬記録、料理記録、掃除記録、タスク管理、お手伝い管理など、生活のさまざまな記録を残し、家族や友人と共有・管理できるようになっています。
React PWA版の確認とiOS/Android版のインストールは以下から。
以下のような画面があります。
カレンダー表示 | 一覧表示 | レポート表示 |
---|---|---|
テンプレートからの作成 | 入力項目のカスタマイズ | 共有機能 |
---|---|---|
) |
日々のログを何のために作ったの?
PWA版をリリースした際のブログで詳細を説明していますが、簡単に言うと、家族のために作成しました。
Flutterに移植した理由
PWA版をリリースした直後、個人開発をしているエンジニアの友人から「日々のログをFlutterに移植するべきだ、Flutterは開発体験が最高だ」というアドバイスを受けました。
その友人がFlutterで開発して公開しているアプリ
実は、「日々のログ」は約2年前にExpo(React Native)で開発されたことがあり、クロスプラットフォーム開発の困難さ(iOSで動作するのにAndroidで動かない、あるいはその逆の問題)を経験していました。そのため、開発を一時保留にしていたアプリです。
クロスプラットフォーム開発の困難さを回避するため、Reactで再開発したバージョンを今年の1月にリリースしました。しかし、本来ならば「気軽にさくさくと入力できる」ことを考えると、ネイティブのモバイルアプリが適しているとは思っていました。
PWA版では、インストールやメンバー招待時のユーザー体験がネイティブアプリと比較して劣ることに不満を感じていました。さらに、データ量が増えるにつれてパフォーマンスが低下する問題もありました。チューニングの余地はありますが、「頑張らないとサクサク動かない」という傾向がありました。
PWAの利用者が増えなかったこともあり、Flutter版を作成することでAppStoreやPlayStoreである程度認知が広がり、利用者が増えることも少しだけ期待していました。
FlutterでHello Worldを試してみたところ、これは良さそうだと感じ、開発を開始しました。
React版とFlutter版の比較
こちらがReact版とFlutter版の比較表です。バックエンドはFirebaseを使用し、フロントエンドのみFlutterに移植しました。
項目 | React版 | Flutter版 |
---|---|---|
言語 | TypeScript | Dart |
フレームワーク | React | Flutter |
UIライブラリ | MUI | Flutter + その他ライブラリ |
状態管理 | Jotai | Riverpod + flutter_hooks |
データアクセス | Cloud Firestore | Cloud Firestore |
認証 | Firebase Authentication | Firebase Authentication |
サーバーサイド | Cloud Functions for Firebase | Cloud Functions for Firebase |
移植の過程
単純なコードの置き換えはChatGPTの助けを借りながら進めました。多少の手直しが必要でしたが、大幅に時間短縮になりました。未使用のFlutterライブラリの使い方など、多くの助けを受けました。感覚的には、約40〜50%のコードがChatGPTによって移植されたものを基にしています。
UIの部分はReactのJSXからFlutterのクラスベースのオブジェクトと違いはありますが、宣言的なUIなので基本的には置き換えていけばよく、移植が容易な印象でした。
Flutterの開発体験
最高でした。Hot Reloading/Hot Restartもあるので、Webでの開発体験と大きく遜色もなかったです。
状態管理
「Riverpod + flutter_hooks」の組み合わせは、「React + Zustand」などと似た感覚で開発ができ、非常に効率的でした。おすすめです。
UIライブラリ
React版ではMUIを使っていましたが、Flutterの場合標準のコンポーネントが充実しているので、「React + MUI」≒「Flutter」な感じでした。
iOSとAndroidの差分
普通にFlutterを使うだけで基本的にほぼ同じ挙動、見た目を実現でき、安心して開発を進めることができました。いくつかのOS固有の挙動に対応する箇所もありましたが最小限の対応で済んだのはFlutterのおかげです。
iOS | Android |
---|---|
Union型からEnumへの変換
TypeScriptで使用していたUnion型は、DartではEnumに置き換えました。DartでもUnion型使いたいなーとは何度も思いました。
export type FieldType =
| 'date'
| 'number'
| 'text'
| 'textarea'
| 'radio'
| 'checkbox'
| 'computed'
| 'file'
| 'rating'
enum FieldType {
date,
number,
text,
textarea,
radio,
checkbox,
computed,
file,
rating,
}
Flutterへの移植の結果
パフォーマンスが大幅に向上し、「気軽にさくさくと入力できる」ことにより近づけました。Flutterへの移植は非常に良い選択だったと感じています。Reactエンジニアでネイティブアプリ開発に興味がある方は、ぜひFlutterを試してみてください。
Discussion