ReactNative での環境切り替え時メモ

# 環境の切り替え対象
* APIのエンドポイントなどの切り替え
    * react-native-config を使用する
* Release, Debug ビルドでの設定の切り替え、Firebase の設定ファイル (GoogleService-Info.plist)
    * iOS, Android のビルド時の設定変更の機能を使用して、切り替える


## react-native-config の導入
```shell
$ yarn add react-native-config
$ react-native link react-native-config
$ (cd ios; pod install)
```

## iOSの環境の設定切り替え
* [こちら](https://gist.github.com/jacks205/45b2721bf2a2b912b1c130aef2572820#ios-instructions) を参考にし、Target のコピー、Scheme 追加
* 6 の pre-action step
    * `PROJECT_DIR` の .env を書き換えるため、ローカル実行時は `ENVFILE=.env.local` を使用するなど工夫する
* `react-run-ios --scheme "作成したTarget名"` で起動する

### GoogleService-Info.plist の配置
* 各 Target の名前のディレクトリを作成しその配下に置く
* XCode で GoogleService-Info.plist を選択 -> TargetMembership で読み込む Target を指定する

### 注意点
* build の Info タブで React のチェックを外さないようにする
    * テスト等、コピー元のTargetにチェックが入っている場合、`react-run-ios` 時にそちらの app が起動してしまう
* [こちら](https://qiita.com/shn/items/e656fe5452e02c0b2853) を参考に Podfile の書き換えを行う


## Android の環境の設定切り替え
* [ProductFlavorの設定](https://developer.android.com/studio/build/build-variants?hl=ja#product-flavors)をしておく
* [こちら](https://gist.github.com/jacks205/45b2721bf2a2b912b1c130aef2572820#android-instructions)を参考に設定
    * 作成した variant 名でを指定 (例: `react-run-android --variant=DevDebug`)


## バージョン/ビルドバージョンの書き換え用のコードの用意
`yarn run set:version {次のバージョン番号} {次のビルド番号}` のような形で起動

```javascript:setVersion.js
const fs = require('fs');
const { execSync } = require('child_process');

const version = process.argv[2];
if (!version) {
  throw 'version が指定されていません';
}
const build = process.argv[3];
if (!build) {
  throw 'build が指定されていません';
}
console.log(`build: ${version}`);

// ファイル文字列置換
const versionFiles = [
  {
    name: 'src/constants.js',
    regex: /export const appVersion.*/,
    replace: `export const appVersion = "${version}";`
  },
  {
    name: 'android/app/build.gradle',
    regex: /    versionName .*/,
    replace: `    versionName "${version}"`
  },
  {
    name: 'android/app/src/main/AndroidManifest.xml',
    regex: /    android:versionName=.*/,
    replace: `    android:versionName="${version}">`
  }
];
const buildFiles = [
  {
    name: 'android/app/build.gradle',
    regex: /    versionCode .*/,
    replace: `    versionCode ${build}`
  },
  {
    name: 'android/app/src/main/AndroidManifest.xml',
    regex: /    android:versionCode=.*/,
    replace: `    android:versionCode="${build}"`
  }
];

console.log("\nreplace version");
for (const file of versionFiles) {
  const data = fs.readFileSync(file.name, 'utf8');
  const target = data.match(file.regex);
  console.log(`  file: ${file.name}`);
  console.log(`     ${target}`);
  console.log(`  -> ${file.replace}\n`);
  const replaced = data.replace(file.regex, file.replace);
  fs.writeFileSync(file.name, replaced, 'utf8');
}

console.log("\nreplace build");
for (const file of buildFiles) {
  const data = fs.readFileSync(file.name, 'utf8');
  const target = data.match(file.regex);
  console.log(`  file: ${file.name}`);
  console.log(`     ${target}`);
  console.log(`  -> ${file.replace}\n`);
  const replaced = data.replace(file.regex, file.replace);
  fs.writeFileSync(file.name, replaced, 'utf8');
}

// ios 設定変更
console.log("\nreplace version in xcode\n");
execSync(`cd ios/ && agvtool new-marketing-version ${version}`, {stdio: 'inherit'});
console.log("\nreplace build in xcode\n");
execSync(`cd ios/ && agvtool new-version -all ${build}`, {stdio: 'inherit'});
```


# 参考
https://github.com/luggit/react-native-config
https://dev.classmethod.jp/articles/xcode-build-environment-adding-scheme/
https://gist.github.com/jacks205/45b2721bf2a2b912b1c130aef2572820#ios-instructions