React Native で development, staging, production など環境を切り替える


基本的に React Native は development か production かしか切り替えができない。

__DEV__

React Native では development かどうかを判別する仕組みとして __DEV__ というグローバルな変数が定義されている。次のページに書いてあるように、 packager に bundle してもらう際、 dev という query prameter に true1 を指定したときに __DEV__ = true としてくれる。

これを見て設定を切り替えればいい。

ちなみに Android で cd android && ./gradlew assembleRelease したり iOS で Release ビルドした場合はきちんと __DEV__ === false にしてくれる。

react-native-config

と、ここまではいいんだけど staging と production をわけたいとなると本体の仕組みだけでは無理になる。

There are no staging vs. production options in the packager. You'll have to determine that at runtime.

react-native-config はここらへんをうまいこと切り分けてくれるパッケージ。

仕組みとしてはビルド時に環境を指定して設定値を native app に埋め込み、実行時にそれを bridge して読み込めるようにする、というもの。

README がとても丁寧に書かれているのでそれを読めばいいんだけど、備忘録代わりに設定方法をひととおり書いておく。

react-native-config は .env というファイルをデフォルトの設定ファイルとして読み込んでくれる。中身は sh 変数の定義のように VAR=VALUE という形で設定値を定義していく。

まず環境と設定ファイルを次のように作っておく。

環境 ファイル名
development .env
staging .env.staging
production .env.production
.env
API_ENDPOINT=http://dev.example.com/api/
.env.staging
API_ENDPOINT=http://stg.example.com/api/
.env.production
API_ENDPOINT=http://prd.example.com/api/

Android

Android の場合、 ENVFILE という環境変数を指定しながら react-native run-android するだけ。 staging 環境のアプリをビルドしたい場合、次で OK 。

ENVFILE=.env.staging react-native run-android

iOS

iOS の場合それぞれの環境ごとに scheme を作る必要がある。

  1. アプリ名と同じ名前の scheme ができているはずなのでそれを duplicate
    • 名前はわかりやすく appname-staging とかにしておく
  2. duplicate した scheme の Build -> Pre-actions に echo ".env.staging" > /tmp/envfile という内容の sh script を書く

↑を .env 含めてすべての設定ファイルに対してやる。 /tmp/envfile というグローバルな状態見てるから毎回書き換えないと前回の状態を引き継いじゃうので。

これで OK 。

使い分け

development かどうかわかればいいという場合は __DEV__ での切り替えで、それ以上に環境を細かくわけたい場合は react-native-config を使えばいい。

mocha と react-native-config

mocha でテストを書く場合、 native app は経由しないというかできない、つまり react-native-config を使おうとすると当然のごとく設定値を読み込めなくて落ちるんだけど、それを何とかする package を @shinout が作ってくれた。

ここらへんの解説もしたいけど、テストについてを含めて今度まとめて書く予定。