React NativeでCodepushもネイティブAPIも対応（Expo Bare Workflow）

React Nativeエンジニアのわくてか（@wktq）です。
今回は僕の所属する**[207株式会社](https://207-inc.com/)**および**[合同会社ヒトベース](https://hitobase.io/)**にて採用している、
「**Expo Bare Workflow**」についてご紹介します。

![79017180-d4ce-11e9-9955-3f0a7be00c7a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/250f479c-4a9a-de84-c4fa-7bc10ec9fb6b.png)
Expoの**Updates API**によって、**審査を通さず**にOTAアップデートでいつでも**コードの更新（codepush）**や**社内テスト**を行えるようにしつつ、Expoでよく問題となる**独自のネイティブコード対応（課金や外部SDKなど）**も可能にします。

# ExpoのUpdates （code push）
Expoは**よく使う共通パッケージ**を盛り込んだ、**Xcode/Android Studioビルド不要でReact Nativeアプリを開発できるツール**です。

アプリを更新する時に、毎回審査を通すのは大変です。
そんなときにExpoのUpdatesを使うとこんなことができます。

```bash
# production-0.24チャンネルへcodepush
expo publish --release-channel production-0.24
```
↑のコマンドで、**AppStoreに提出済みのアプリ上のJavaScriptがまるっと更新されました。**
**これによってアプリ開発においてコスト・ボトルネックとなるAppStore / GooglePlayの審査が不要になります。**

![i.fig](https://media.giphy.com/media/l0MYJnJQ4EiYLxvQ4/giphy.gif)

ここまではExpoを使用したことがある方なら理解していると思います。ここで、問題点もあります。

Expoの仕組みとしては、**react-native-unimodules**がpod経由でインストールされます。こちらは**expoの機能で使用するネイティブ関連のpodとそのリンクをラップしたもの**です。

**Expo単体だとunimodulesに入っていないネイティブ機能（例えば課金や外部SDKなど）に対応できないことがあります。**


# Expo Bare Workflowについて
そこで、**ExpoのBare Workflow**の出番です。

**OTAアップデートを含むExpoの機能**を残したまま、**Xcode**および**Android Studio**でのビルドが可能になります。
これによって、独自のpodやネイティブコードの注入が可能になります。

もちろんこれに関しては、[react-native-code-push](https://github.com/microsoft/react-native-code-push)や、そもそもReact Native以外のソリューションもありますが、全体がwrapされシームレスに（~~ややこしいappcenter等に依存せずに~~）、しかも安定して動くのでこちらを使っています。

### 実際のコード＆コマンド
```jsx
import * as Updates from 'expo-updates';
import { AppLoading } from 'expo';

async expoUpdateReload() {
  const update = await Updates.checkForUpdateAsync();
  if (update.isAvailable) { // アップデートが利用可能か
    await Updates.fetchUpdateAsync(); // JSバンドルをダウンロード
    Updates.reloadAsync(); // アプリをリロード（一瞬白くなります）
  }
}

render() {
  const { store, persistor, isReady } = this.state;
  if (!isReady) {
    return (
      <AppLoading
        startAsync={this.expoUpdateReload}
        onFinish={() => this.setState({ isReady: true })}
        onError={console.warn}
      />
    );
  }
  return <Main />
}

```
アップデートを行う場合は、expo publishコマンドを利用します。

```bash
# production-0.24チャンネルへcodepush
expo publish --release-channel production-0.24
```

これだけで、としてビルド・提出したReact NativeアプリのJavaScriptが書き換えられます。

もちろん**CIツール等と組み合わせて自動デプロイも可能**です。弊社207incではGithub Flowでmasterが更新された際に、CircleCIでproduction-*.**へ自動的にデプロイされる仕組みになっています。

# でもExpoって評判悪いよね。
eject※や挙動の不安定さから、僕も昔は嫌いでした。

`※ Expoでは非対応のネイティブ機能を実装する場合に、「eject」という作業をする必要があります。
弊社でもExpoのejectを行いましたが、エンジニア1人まるまる1ヶ月以上の稼働でやっと完了しました。`

ただし、Expo Bare Workflowを導入すると、
**すでにejectされた状態でinitし、さらにExpoの機能を使えます**。

（Expo Bare Workflow + OTAアップデートは**2020/03 [SDK v37]**より使用可能になりました。）

また、関連APIや環境の不具合も昔はよくありましたが、[最新のSDK](http://expo.io/)ではかなり改善しています。

# 本当に審査がいらないの？
いくつか審査が必要なタイミングがあります。

- **ネイティブモジュールを追加する場合**
- **リンクのSchema変更などで、Info.plist / Manifestを書き換えたい場合**
- **expoのSDKバージョンを上げたい場合**

ざっくりこういった場合です。

またhttps://qiita.com/muzou/items/5b990e03cb1a4084e33d こちらの記事で触れられているように、**OTAアップデートのバージョン管理方法については注意が必要です。**間違ったバージョンに向けてexpo publishを行えば、壮大にクラッシュしかねません。

# リリースチャンネル（バージョン）管理方法
後ほどアップデート予定
管理方法については長くなるので別途記事を書こうと思います。

# Flutterよりいいの？
![スクリーンショット 2021-01-06 15.25.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/ebe505d2-f299-e723-7cf2-dcfefb067aea.png)

今のところはFlutterだと**OTAが公式対応されていない**ことや、まだthird partyがReact Nativeの方が充実している（60% - 70％のイメージ）ことから、現状はReact Nativeを採用しています。

また、僕はフロント出身でReactの方が直感的（視覚的に）に書けるので、個人的にはReact Nativeが好きです。
要件によってはFlutterの採用も検討しているとかいないとか。

KotlinかけるならMPPも選択肢としてありそうです。
https://www.wantedly.com/companies/wantedly/post_articles/282562

# Join Us
弊社207, Incでは、エンジニアを絶賛募集中です！この**Expo Bare Workflow**および**GraphQL**でゴリゴリ開発したいReact Nativeエンジニアの方はぜひ募集を見てみてください！
![7fea906a-12c2-45c6-a006-c2985f65f86a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/f08cd471-175b-cd64-1bed-deee15376bbb.png)
**[急成長中の物流Techベンチャーを牽引するフロントエンドエンジニアを募集！](https://admin.wantedly.com/projects/555011/edit)**

会社概要：
https://207-inc.com

# まとめ
React Nativeで新規プロジェクトを作る場合で、特にパッケージ容量などのこだわりがなければ**Bare Workflow**で始めることをお勧めします。

**開発の速度は間違いなく上がり**ますし、expo publishのバージョン管理や命名規則だけしっかり行っていれば、問題なく運用できるかと思います。

詳しく聞きたい方はTwitterのDMまで！
https://twitter.com/wktq_tenova
![スクリーンショット 2021-01-06 15.25.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/64e78787-a278-3ad9-d2ed-9d4c342e6443.png)