@kinakobo です。
先日フィークルという新規サービスのiOS, AndroidアプリをReactNativeで開発し、リリースしました。
すでに国内でもいくつか採用事例があるReactNativeですが、まだまだ事例が少ないと感じます。
今回自分たちもReactNativeを採用したので、まずはその検討段階から紹介したいと思います。 また、開発チームはWebエンジニアのみで構成されていたため、特にWebエンジニアの方向けの内容になります。参考までに、開発チームの人数は4人でAPI側も同じメンバーが担当していました。
はじめに、ネイティブアプリを何で作るか検討した際に出た選択肢は以下の3つでした。
1は全く知識がない状態から始めることになるため、最も学習コストが高いです。作ろうとしているものがまだ検証段階のサービスであったこともあり、長い時間やコストをかけて開発を行うべきではなく、選択肢から外しました。
2はチーム内にReactの経験者が数名いたため、有力な選択肢でした。しかし、ネイティブアプリの開発経験がないため、ビルド周りやネイティブのコードでエラーが発生した時などに多少不安がありました。
3は最近勢いがあるものの、ReactNativeと比較すると採用事例が少ないことや不明確な点が多いため選択肢から外しました。
このような経緯でReactNativeを採用することに決めました。ネイティブの知識不足に多少不安があったものの、社内のアプリエンジニアにいつでも質問できる環境だったことが選択の後押しになりました。
そんなこんなでアプリ開発をはじめ、リリースまで漕ぎ着けることができました。結果的にReactNativeにして正解だったと思います。
開発の際にいくつか検討が必要なポイントや使ってみて良かったと思える技術があったため、以下で紹介します。
作り始める前に検討したいこと
Expoを使うかどうか
ExpoはReactNativeでの開発を支援するサービスです。詳細は割愛しますが、Expoを使うとネイティブのコードを一切記述する必要なく、JSのコードを書くだけでReactNativeアプリを作成し、リリースすることができます。
これだけ聞くととても便利が気がしますし、実際便利なのですが、ネイティブモジュールを追加することができないというデメリットもあります。プッシュ通知など多くの機能はExpoで用意されていますが、それらで事足りなさそうな場合はExpoを使わない方が無難です。用意されている機能はこちら(Expo Documentation)の左サイドバーから一覧できます。
事足りることがわかっていて、ネイティブのコードに関する知見がない場合はExpoを使うと良さそうです。
iOS、Androidでデザインを分けるかどうか
今回は分けないことにしました。同じコードを使い回しにくくなり、ReactNativeを使うメリットが薄れると思ったためです。
また、デザインやアニメーションをプラットフォーム毎にとことん突き詰めたい場合は、ReactNativeはあまり向いてないとも思います。
ですが日付選択のUIなど、どうしても分けたい部分がいくつかありました。そういった部分は、プラットフォーム毎の違いを吸収してくれる外部ライブラリに頼りました。 日付選択の場合は react-native-datepicker を使用しました。
今回は使用していませんが、様々なUIコンポーネントをプラットフォーム毎に良い感じの見た目で表示してくれるNativeBaseというコンポーネントライブラリもあります。
あらかじめ知っておくと良い技術
React
言わずもがなな感じがしますが、ほぼReactのコードを書くことになるので、ReactでSPA等の開発経験があると覚えることが少なくて済みます。
特にReduxなどのFluxアーキテクチャはReactよりも理解に時間がかかった覚えがあるので、使ったことがないと学習コストが跳ね上がる気がしました。
iOSとAndroidアプリの開発経験
Expoを使わずに素のReactNativeで開発する場合、特にビルド周りでiOS/Androidの知識が必要になります。 そのため、チームに1人以上アプリエンジニアがいた方がビルド周りやネイティブコードのエラーで変に嵌ったりすることが少なくなります。
自分たちの場合は、チーム内ににアプリエンジニアがいなかったため、iOSとAndroidを扱う他チームのアプリエンジニアにいつでも質問できる状態にしてもらいました。
使ってみて良かった技術
TypeScript
最初はコード量増えて面倒臭いという声もありましたが、開発が進むにつれメリットが上回り、結果的に大満足でした。 具体的には、
- エディタでコード補完と定義元にジャンプできる。
- リファクタリングをするときに安心感がある。
- コードを読むときに型がわかるので、読み解きやすくなる。
- コンパイルエラーにより単純なミスを防げてコードレビューのコストが下がる。
- TSLintを導入することでさらにレビューコストを下げることができる。
といったメリットがありました。
自分は使ったことがありませんが、Flowでも同じようなことができると思います。
Prettier
JavaScriptの用のコードフォーマッターです。デフォルトの設定でもかなり綺麗に直してくれるので、導入しない手はないと思いました。これもTypeScriptと同様にコードレビューのコストを下げてくれました。
また、自分たちの場合はコードフォーマット済みかをCircleCIでチェックするようにすることで、フォーマットしていないコードがマージされるのを防ぎました。 後から知りましたが、pre-commitというパッケージを用いてコミット時にPrettierを実行する方法が一般的のようです。
Redux
ReduxはReactのstate(状態)を管理をするためのフレームワークです。 Reduxを使うとReactComponentからstate管理を引き剥がすことができます。stateをなくしたReactComponentは、受け取ったpropsによって必ず同じ結果を返すだけのものになり、責務が明確になります。
また、Reduxは一般的にaction, reducer, constantsでファイルを分割しますが、それらは密結合になっているので、1ファイルにまとめようというDucksパターンを採用しました。このパターンで書いてみて特に困ることはなかったので、メリットしかないという印象でした。
MobXも検討しましたが、こちらの記事(ReduxとMobXの選定観点) を参考にして、Reduxの方が用途に合ってたのでReduxを採用しました。
CodePush
CodePushを使うと、アプリのJS部分をアプリストアの審査なしで変更することができます。そのため、JS部分で完結するリリースは即座に差し替えることができます。
と言っても最近は3日もあればストアの審査が終わるので、CodePushがなくて困るという場面はさほどないと思います。余裕があれば入れてみる程度でも良いかもしれません。
また、CodePushを提供しているAppCenterというサービスは、CodePush以外にもアプリのビルドやテスト、クラッシュレポートの管理機能などを備えています。公式ドキュメントでReactNativeをサポートしている点もありがたいです。
実際にビルドの機能を使用していますが、GitHubと連携して特定のブランチに対するコミット毎に自動でアプリをビルドして、テストアプリを社内配信するところまでを簡単な設定で行ってくれて便利です。
最後に
ReactNativeに慣れるとReactでSPAを作る感覚でネイティブアプリを作ることができます。ネイティブアプリを作ったことがない自分にとっては、作れる物の幅を広げてくれる素晴らしい技術でした。
この記事がReactNativeを検討している方の参考に少しでもなれば幸いです。
クラウドソーシングのクラウドワークスでは、成長し続けたいエンジニアを募集しています!