React Nativeでの高速プロトタイピング・MVP開発のためのTips7つ (firebase / gas / google cloud function) 

## はじめに
はじめまして、株式会社ムゾウの渡辺と申します。
ReactNative、サイコーですね。

特にサービスの開発初期のタイミングでのプロトタイピングや、ユーザービリティの改善のための時間が大幅にスピードアップした気がします。

「そのボタン、もっと大きくできないの？？」といったディレクター/デザイナーからの注文についても、hot loadingをonにして、あーでもないこーでもないと見ながら進めることができるのが個人的にサイコーです。


が、とはいえ、1分でも1秒でも開発速度が上がればさらにうれしいですよね。
プロトタイピングやMVP開発の際に、個人的に実践しているTipsや使っているライブラリをまとめてみました。


## case1) 開発環境構築するのが面倒。。
https://snack.expo.io/
を使いましょう。
URLを開いた瞬間始められます。


**所感：**
瞬間的に動くので感動するのですが、機能も限られているので、パフォーマンス的に見せるという以外では使ったことないです。。
あと、個人的には普段使っているエディタで書きたいので。
そもそもreact-native自体、開発環境の構築にそこまで大変なことがないと思うので参考程度に。。


## case2) UIのスタイリングが面倒、、まだデザインのモックアップも上がってきていないし。。
NativeBase
https://nativebase.io/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/206623/cd103a32-7cfc-c131-36e3-e6bafed8f8bc.png)

を使いましょう。

ボタンやカードなど、基本的なComponentがすぐに使えます。
React-nativeにおけるBootstrap的なイメージで使っています。

**所感：**
最初はいいのですが、もしすでにデザインがあるのであれば、導入するか否かは一度よく考えてみたほうがいいかもしれません。
OS間の差分を吸収するのはいいのですが、オリジナルのデザインを反映したい場合など、意外に自力でスクラッチから書いたほうが早くて自由度も高かったり。

そして、Componentをできるだけ使いまわせる形でたくさん作っておくと、組み合わせるだけで大体のUIは作れるようになるので、以後のページ作成の速度が劇的に上がる気が。

**番外編**
「react-native template」で検索したり、mediumのreact-nativeタグを見ていたりすると、bootstrapのテーマ的なノリでテーマを販売している人がいたりします(似たようなテーマを何人かが販売していたりもするのでいかがわしいところもあるのかもしれませんが、、)
もし作るものが似ていたりする場合にはそういったものも買って見てもいいのかもしれません。
https://code.tutsplus.com/articles/best-react-native-app-templates--cms-29602

コードディングスタイル的なものが違ったりもするので、学習用と割り切って買ってみて、やり方だけ真似る、というのが自分としては一番勉強になりました。

## case3) データがない！ その1
開発の初期や新機能開発時など、シードのデータもエンジニア側で準備してしまったほうが早いケースがあります。
最初の頃は、↓みたいなところや
```
src/
└repository/dummy.json
```
config/xxxみたいなところにjsonファイルで置いて置いて、それをaction/reducerで読み込んで使っていました。

**所感**
最終的には消すファイルなのと、リレーショナルなデータで整合性をとったり、都度書き換えたりが面倒になったのでやめました。
本当の最初の最初にだけ。

## case4) データがない! その2
上記の通り、.jsonファイルなり、export const = [{hoge: bar}] なり、適当にデータを作っていたのですが、
例えば100要素のオブジェクトで、何か項目を追加したい、だったり、よりリアルなデータにディレクター側で変更したい！だったり、、
というのが結構つらく、最近はgoogle spreadsheet + app scriptを使った方法に変えています。

**HOW TO**
・スプレッドシートを作る
　↓
・テーブルごとの単位でシートを作る
![image.png](https://qiita-image-store.s3.amazonaws.com/0/206623/dbe219af-7fe5-e245-82c4-d98c88cded96.png)
 ↓
・シートの中のデータをjson形式に変えるスクリプトを書く
参考：https://liginc.co.jp/179788
↓
・getでの問い合わせを受けられるようにしてwebアプリケーションとして公開
参考： https://qiita.com/hirohiro77/items/a947416f803f45777338

これだけで簡易APIが作れるので、サーバー側とつなぎこみがまだでも、実際に近い形でプロトタイピングを進めることができます。サーバーといざ繋ごうというタイミングでも向き先やパラメータを変えるだけなので、プロト開発以後がスピードアップする小ネタかと思います。

また、ダミーと割り切って使っているので込み入ったことはやっていないですが、そこそこのロジックはスプレッドシートでも組めるかと思います。
下記のようにgetのパラメータでシート名を指定するようにしておけば、テーブルが増えてもシートを追加するだけなので簡単にダミーデータを追加でき、ストレスレスです。
https://script.google.com/a/muzou.jp/macros/s/XXXXXXXXX/exec?table_name=items

**所感**
個人的にマスタ系のデータはspreadsheet管理が最強と思っているので、実際の運用の際には
Spreadsheet => rails => RDBみたいにデータを入れるスクリプトも作ったりしています。

また、後述するfirestoreにもスプレッドシートからデータを入れることができ、入力の管理画面の代理として使ってたりもします。
参考：https://qiita.com/muzou/items/ab215e6e9da93926600e

## case5) サーバー側がまだ実装されてない、、がクライアントの実装を進めたい。。
静的なデータをレンダリングしたり、画面遷移を確認できるようになったあとには、きっと動的なアクションや、実際のデータ書き込みもつくりたくなるものですよね。

そんな時には Firebaseを使って、サーバーレスでアプリの開発を進めるのはどうでしょうか。
複雑なロジックがなければ、サーバーレスのまま開発を完了することも可能です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/206623/75dd3be4-20ed-db99-e489-6cdd59e52db0.png)

高機能なFirebaseの中でも特におすすめなのが、Firestore。
まだfirestore自体はβなのですが、react-native-firebaseでもv3.X以上でサポートされています。
react-native自体のversionが0.48以上なので古いversionを使っている場合はアップデートが必要なので注意です。
https://github.com/invertase/react-native-firebase

![image.png](https://qiita-image-store.s3.amazonaws.com/0/206623/8d44d4f5-f4d7-8237-1a48-c7ca99dbaebd.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/206623/c0d06446-3016-9eb5-8a03-0c85d3783ae2.png)

Firestoreは導入、使用法もかなり簡単です(firebase自体の組み込みが終わっている前提)

####導入
ios
```pod 'Firebase/Firestore'```

android

```java:android/app/build.gradle

dependencies {
  // ...
  compile "com.google.firebase:firebase-firestore:11.6.0"
}
```
```java:android/app/src/main/java/com/APPNAME/MainApplication.java
// ...
import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.firestore.RNFirebaseFirestorePackage; // <-- Add this line

public class MainApplication extends Application implements ReactApplication {
    

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new RNFirebasePackage(),
          new RNFirebaseFirestorePackage() // <-- Add this line
      );
    }
  };

}
```
#### 使用法
https://medium.com/@callMeNorm/prototyping-react-native-with-appetize-io-752f6d303668
https://firebase.google.com/docs/firestore/query-data/get-data

```js:
//コレクションへのリファレンスの取得
this.ref = firebase.firestore().collection('todos');

//データの追加
  this.ref.add({
    title: this.state.textInput,
    complete: false,
  });

//データの読み込み
var docRef = firebase.firestore().collection("cities").doc("SF");

docRef.get().then(function(doc) {
    if (doc.exists) {
        console.log("Document data:", doc.data());
    } else {
        console.log("No such document!");
    }
}).catch(function(error) {
    console.log("Error getting document:", error);
});
```

その他にも、個人的にプロジェクト作成時に下記はまとめて入れています。
Firebase Auth
Firebase Crash
Firebase Analytics
Firebase Messenger (これだけreact-native-firebaseを使わず、react-native-fcmを使用しています)

**所感**
firestoreでは、realtime databaseではなかった簡単なクエリも使えるようになっているため、今まで以上にできることが広がった感があります。
パフォーマンス面やチューニング方法など、RDBとまた違ったところもあるかと思うので、大規模になった際に本当にProductionに耐えうるのかは未知数ですが、MVPぐらいでサーバー側も工数さけない場合には選択肢として良いのではないかと思います。


## case6) ほんのちょっとだけサーバーで処理をしたい。。そのためだけにサーバー立てるのが面倒。。
amazon lambda、api gateway、でもいいのですがfirebaseをガリガリ使っているのでgoogle cloud functionを使いました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/206623/3a773a07-2462-59c9-cc1e-6e43c0a094db.png)

具体的にはIn App Purchaseのレシートの検証とログの記録をcloud functionで行うことがありました。
es6で書いてbabelでトランスコンパイルして、アップしています。

参考までですが、
IAPの組み込みはreact-native-in-app-utils
https://github.com/chirag04/react-native-in-app-utils

レシートの検証はこちらのindex.jsを参考に使いやすいように改変して作っています。
https://github.com/sibelius/iap-receipt-validator

**所感**
レシートの検証くらいだといいのですが、込み入ったロジックの場合はrailsなりなんなりで普通に作ってしまったほうが早いかもしれません。
あとは、、費用面はどうなんでしょう。

## case7) ディレクターが確認しているアプリのversionが古かった。。
「あれ、このバグまだ治っていないの？？」みたにいわれて見てみるとアプリのバージョンが古かっただけ、ということ結構ありますよね、、。僕だけでしょうか。。

正攻法でci経由でhockeyappやbetaなどでアプリを配布してもいいのですが、code-pushだとアプリを開き直してるだけで自動で反映されている、というのが素敵ポイントです。
jsのbundleだけだとアップするのも一瞬で終わるので、1秒でも惜しいときにはcodepushで配布するのが吉です。

**所感：**
codepush自体は本番での修正、改善などでも使えるのでせっかくreact-nativeを使うのであれば入れて置いて損はないと思います。
※　Microsoft app center の一部になるようなのですが、firebaseとapp centerと両方になると辛いところもあるので、2018年の動向が気になっています。

## その他、開発速度を上げるためにやった細かいこと
・ ビルドを並列にする(iOS/Android)
NativeModuleで外部から読み込むファイルが多い時に結構違う気がする
ビルドは早ければ早いに越したことがないです

・ ESLint/pretterは入れる
整形に時間を使うのはさすがにばからしいので

・ iosシミュレーター２台使い
https://qiita.com/muzou/items/e16e6283b1777bdd25b0

・ Atomのsnippetをどんどん追加する
redux関係とかは結構同じコード書いてたりするので)
よく使うstyleとかもsnippetに登録してしまっています

・・etc

## おわりに
改めて読み返してみると、「実際に動くものをクライアント側だけで極力早く作りたい」、という視点が強いまとめでした。Firestoreとか。

UIや遷移だけの確認であればSketchなり、Prottなりいろいろと方法があると思うのですが、
React-nativeを使うとちょっとしたロジックを組み込んだアプリも簡単に作れることが魅力だと思っています。

UIのコンポネント作成の高速化に関してはstorybookなど、デザイナー<=>エンジニア間のコミュニケーションツールがいろいろと出てきているようなので、今後試して見たいと思っています。

宣伝：
弊社ではReactNativeでの仕事を強化中です＾＾
開発パートナーも開発案件も両方募集中ですので興味あるかたいましたらご連絡お待ちしてますmm

http://muzou.jp/
info@muzou.jp