2021年版 Expoまとめ

https://github.com/expo/expo

https://blog.expo.dev/expo-sdk-43-aa9b3c7d5541

- Expoのここ３年くらいの動きが慌ただしかったため、用語整理も兼ねてまとめる

# Expoのリリース履歴

| SDK | Date | Highlight |
| -- | -- | -- |
| [33](https://blog.expo.dev/expo-sdk-v33-0-0-is-now-available-52d1c99dfe4c) | 2019/6 | Bare Workflow<br>Expo Web(React Native Web)ベータ版<br> |
| [34](https://blog.expo.dev/expo-sdk-34-is-now-available-4f7825239319) | 2019/7 | `Android App Bundle(.app)`をサポート |
| [35](https://blog.expo.dev/expo-sdk-35-is-now-available-beee0dfafbf4) | 2019/9 | `iOS13`をサポート |
| [36](https://blog.expo.dev/expo-sdk-36-is-now-available-b91897b437fe) | 2019/12 ||
| [37](https://blog.expo.dev/expo-sdk-37-is-now-available-dd5770f066a6) | 2020/4 |  |
| [38](https://blog.expo.dev/expo-sdk-38-is-now-available-ab6cd30ca2ee) | 2020/6 | ExpoKit終了 |
| [39](https://blog.expo.dev/expo-sdk-39-is-now-available-4c10aa825e3f) | 2020/9 | `iOS14`をサポート |
| [40](https://blog.expo.dev/expo-sdk-40-is-now-available-d4d73e67da33) | 2020/12 | |
| [41](https://blog.expo.dev/expo-sdk-41-12cc5232f2ef) | 2021/4 | `EAS Build`,`EAS Submit`提供開始<br>`AndroidR(11/SDK30)`をサポート<br>`iOS10`を除外 |
| [42](https://blog.expo.dev/expo-sdk-42-579aee2348b6) | 2021/7 | `expo-dev-client`のpreview release |
| [43](https://blog.expo.dev/expo-sdk-43-aa9b3c7d5541) | 2021/10 | `iOS15`をサポート<br>`iOS11`を削除|
| [44](https://blog.expo.dev/expo-sdk-44-4c4b8306584a) | 2021/12 | |

動きを大まかにまとめると、

- 2018/12ごろの「 [ExpoKit 2019 - And bringing Expo APIs to bare React Native](https://blog.expo.dev/expokit-2019-1e5cb02106f8) 」で、それまでのExpoKit（なんだっけこれ）での開発体験がよくなかったとのことで、Bare Workflowの構想が始まる
- 2019/6のSDK33でBare Workflowがリリースされる
- 2019年はそれまでのモノレポ(`@expo/expo`)から`react-native-unimodules`への分離・移行が進む
- 2020/6のSDK38でExpoKit終了
    - [今後はBare Workflowに完全に移行すると宣言](https://blog.expo.dev/time-to-start-using-expos-bare-workflow-expokit-now-deprecated-d6052890c18b)
- 2021/1にEAS Build発表
    - ※この辺の流れが不明
- 2022/6予定のSDK46で従来のビルド(Classic Build、`expo build`)のサポート終了
    - [2023/1/4でクラウドビルドサービスも停止と発表](https://blog.expo.dev/turtle-goes-out-to-sea-d334db2a6b60)

# クラウドビルド

- [expo.io](https://expo.io)によるクラウドビルドによって、**アプリ開発環境をローカルに構築しなくても**リリースビルドまで作れてしまう機能を早くから提供していた
    - ※ただし、アプリストアへのリリースは、ビルドを手でDLして手で上げにいく形だった
- ※いつの間にかドメインが [expo.dev](https://expo.dev) に変わっていた
- リリースに必要なAndroid/Appleの証明書等はexpo.io上に預けておくことができる
    - 以前はexpo.ioにログインしても預けた証明書等を見ることはできなかったが、2021年のEAS Submitリリースに合わせて管理画面も刷新し証明書の閲覧や更新が画面上で出来るようになった
- （記憶違いかもしれないが）Organizationアカウントにメンバーを招待することができたが、以前は`eas build`を実行するときにログインするユーザーはオーナーアカウントではなくてはならず、チーム開発しにくかった
    - いつのまにか [**app.json**に**owner**の項目](https://docs.expo.dev/versions/latest/config/app/#owner) が出来ていて、organizationに招待されていればメンバーのアカウントでもコマンドが使えるようになっており、**チーム開発もしやすくなった**

# リリースサイクル、SDKバージョン

- ２年ほど前に今後のリリースサイクルが発表され、3カ月ごとに年4回リリースされることになった
    - 直近は2021/12にSDK44がリリースされた
    - 予定通りだと2022年は45,46,47,48がリリースされるはず
- 最新バージョンから数えて４バージョンしかサポートされない
    - サポートが外れたバージョンはExpo Goでビルドできない

# ネイティブコード

- 非常にややこしい話だが、ReactNativeを使っているはずのExpo SDKで開発したアプリでもReactNativeのネイティブ部分を自由に扱うことはできなかった
    - サードパーティのReactNativeモジュールをインストールしてもネイティブコードの修正部分をアプリに反映することができないため正常な動作とならず、利用できるモジュールは限定的だった
    - ※GoogleAnalyticsのReactNative SDKなどを入れても何も送信されることはなかった
- また、Expo SDKで利用しているReactNativeはExpo用のForkプロジェクトであり純粋なReactNativeではなかった（[Expo42まで](https://blog.expo.dev/expo-sdk-43-aa9b3c7d5541#:~:text=more%20react%2Dnative-,fork,-in%20Expo%20managed)）

# Bare Workflow

- SDK33より **Bare Workflow** が登場した
    - `$ expo eject` コマンドを実行することで、`ios/` `android/` フォルダにネイティブコードが生成されるというものだった
    - 生成されたフォルダはXcodeやAndroid Studioでそのまま開くことができ、これによりネイティブコードも好きにいじれるようになった
        - その反面、Expoの恩恵には与れなくなり、**アイコン類の自動生成**、**Expo Goでの実行**、**クラウドビルド**、**証明書の管理**、**PUSH通知** など多くの機能が手作業実装となり手間が増えた
        - Expo SDKのバージョンアップ後にもネイティブ側への必要な修正を手作業で行う必要があり非常に手間であった
            - ※SDK40で`expo eject`は[繰り返し実行可能](https://blog.expo.dev/expo-sdk-40-is-now-available-d4d73e67da33#:~:text=Expo%20config%20by-,re%2Drunning,-expo%20eject%20%E2%80%94%20we%27ll)になった？（未検証）
- Bare Workflowが登場したことで従来のexpo.ioを用いた開発方法は **Managed Workflow** と呼ばれるようになった

# Managed Workflow in 2021

- [Expo managed workflow in 2021 - Apr 22, 2021](https://blog.expo.dev/expo-managed-workflow-in-2021-d1c9b68aa10)
- 2021年4月のSDK 41より、新しいビルド方法による開発フローが利用できるようになった
- **EAS Build** によりネイティブコード生成を含むビルドもクラウドビルドすることが可能となった
- また、ビルドだけではなくストアへのリリースまでサポートすることが発表された (**EAS Submit**)
- EAS は **Expo Application Services** の略

# Automatic TypeScript setup

- [SDK 41](https://blog.expo.dev/expo-sdk-41-12cc5232f2ef#:~:text=Automatic%20TypeScript%20setup)で発表されていた
    - ※見逃していたため未検証
    - `tsconfig.json`だけ作って普通にrunするとTypescriptにコンバートしてくれるらしい？

# Expo Goとexpo-dev-client

- **Expo Go** (後に**Expo Client**に改称) はAndroid/iOSのアプリとして提供されており、開発環境でビルドしたReactNativeのJSバンドルをアプリに転送し実行する仕組みだった
    - ここが「アプリ開発環境がなくても開発できる」というExpo最大の見せ場であった
    - アプリ自体は既に完成したものを利用しているため、当然ながらネイティブ部分にアクセスするような開発はできなかった
- 新しく登場した [**expo-dev-client** (Custom Development Clients?)](https://blog.expo.dev/introducing-custom-development-clients-5a2c79a9ddf8) では、Android/iOSのプロジェクトソースを自動生成しアプリそのものをその場でビルドしてしまうことができるようになった
    - expo-dev-client利用時のExpo Goはランチャー程度の役割しかないので、あってもなくてもよい（はず）
- その代わり、ローカルでビルドする場合はそれなりにAndroid/iOSの開発環境が必要になった
    - ※この点はEAS Buildで解決する（後述）
- アプリそのものをビルドすることができるので、全てのReactNativeのサードパーティモジュールが動作するようになった
- ネイティブプロジェクトのソースは自動生成なため、Expo SDKのバージョンアップ時にもBare Workflowのときのような手作業をしなくてよくなった
- `$ expo prebuild` コマンドでネイティブプロジェクトのソースが生成される（アプリビルドは行われない）ため、生成されるソースの確認やXcodeでのデバッグなども行うことができる

# Config Plugins

- ネイティブプロジェクトのソースを個別に編集せずにアプリの設定をカスタマイズできるように、[**Config Plugins**](https://docs.expo.dev/guides/config-plugins/)が提供されている
- `Info.plist` の特定部分を書き換えたり、`entitlements` に設定を追加したりできる
    - https://docs.expo.dev/guides/config-plugins/#default-mods
- `withDangerousMod` を使えばかなり危険な書き換えもできる（未検証）


# EAS Build

- [EAS Build — February Preview Update - Feb 19, 2021](https://blog.expo.dev/eas-build-preview-update-1-6c38204a63f5)
- expo.dev上のクラウドビルドが新しいビルド方法で行われるようになった
    - ※従来の`expo build`コマンドでのビルドの履歴は「`Type: Classic`」と表示されるようになった
- [**eas.json**](https://docs.expo.dev/build/eas-json/) でビルド設定を書けるようになった
  - 証明書を切り替えたり、ビルドイメージを指定できたりする
  - 環境変数的なものも設定できる
- ビルド前後に[**hook**](https://docs.expo.dev/build-reference/how-tos/#eas-build-specific-npm-hooks)を動作させることができるようになった
- クラウドビルド用のシークレットも預けておけるようになった
- 生成されるバイナリ**容量が1/10**程になった
    - ※今まで単純なWEBVIEWアプリでも80MBになったりしていたが、不要なコードが含まれなくなったため10MB以下になることも普通になってきた
- 開発用に（expo-dev-clientを有効にして）ビルドしたアプリは**ローカル開発**に利用できる
    - ※（従来のExpo Goのように）アプリの開発環境のないマシンでも、 EASでビルドした開発用アプリをスマホに入れてPCで `$ yarn start --dev-client` してQRを読み込めば開発ができる
        - ※ただし、ネイティブ部分を変更したい場合はアプリの再ビルドが必要

# EAS Submit

- [Expo Application Services (EAS): Build and Submit - Dec 16, 2020](https://blog.expo.dev/expo-application-services-eas-build-and-submit-fc1d1476aa2e)
- Play Store/AppStoreへのバイナリアップロードと新バージョンのトラック作成まで自動化できる


# 最新版(SDK43)でのリリースフロー

![MatchaNote2021-Architecture-Expo.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/184ea090-32c7-446d-bc99-6e81f1e620e2.png)

- 諸々設定済みであれば `$ eas build -p all --non-interactive --auto-submit` と打って待っていれば諸々自動的に動いてくれる
    - Androidはどこに出すかを選べる（内部テスト・クローズドテスト・オープンテスト）
    - リリースノートやリリースのバージョン名を書き換える機能は今のところは無さそう
- 図では省略したが、ビルド時のHookで各サービスとの連携もできるのでいろいろ便利に使える
    - 各所（Slackなど）に通知したり
    - AmplifyをpullしてGraphQLをビルドしたり
    - `google-services.json` をSecret化しておいてビルド前にファイルに戻したり
- こちらも省略したが、PUSH通知用のKEY類も預けておけてExpo経由で通知できる機能も健在

# Bare Workflowで作ったアプリをManaged Workflowに戻せるか

- 戻せる（実績あり）

# まとめ

- 今後は、**Managed Workflow**＋**EAS Build**＋**EAS Submit**が推奨されていくのだと思う