0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React Native / Expo】EAS Update完全入門:仕組み・適用範囲・ハマりどころの実装ログ

Posted at

OTA Updateとは

OTA の意味

OTA(Over The Air)Update とは、アプリを再インストールせずにネットワーク経由で更新を配信する仕組みです

Webでいうと:

1. JS / CSS を差し替える
2. ページをリロードする

に似ていますが、ネイティブアプリでは仕組みが異なります

ネイティブアプリでいう OTA Update

ネイティブアプリ(iOS / Android)では通常

1. App Store / Google Play に提出
2. 審査
3. ユーザーが更新

というフローが必要です

OTA Updateを使うと:

1. JavaScript(ロジック・UI)だけ更新
2. サーバーから直接配信
3. ユーザーは再インストール不要

という更新が可能です

Expo ではこれを EAS Update(expo-updates) として提供しています

どこまで OTA Update をやっていいのか?

ここが一番重要なポイントです

結論からいうと:
「ネイティブ挙動を変えない範囲の JS 更新」まで

App Store(Apple)の考え方

Apple の App Store Review Guidelines には、
OTA Update を明示的に禁止する条項はありません

ただし、公式に「許可する」という声明もなく実務上は、アプリの実質的な機能変更ではないかどうかの判断が審査チームに委ねられています

Apple が気にするポイント

  • アプリの主目的や主要機能が変わっていないか
  • ストア申請時の説明と挙動が乖離していないか
  • ユーザーにとって誤解を招く変更になっていないか

そのため、一般的には問題ないと判断されやすい例:

  • バグ修正
  • UI文言の変更
  • 表示や軽微なUX改善

注意が必要な例:

  • メイン機能の追加・削除
  • 課金フローや決済仕様の変更
  • アプリの性質が変わるレベルの更新

という線引きで考えられることが多いです

Google Play の考え方

Google Play では、
実行可能なネイティブコードを Google Play 以外から更新することは原則禁止されています

ただし:

  • JavaScript
  • HTML
  • インタープリタ上で動作するコード

については 例外として扱われるケースがある とされています
これは React Native / Expo OTA が一般的に許容されている理由でもあります

実務上は以下の点が重要です

  • .dex / .so などのネイティブコード → OTA 不可
  • JS / アセット → OTA 可能(ただし責任は開発者側)

OTA Update を試してみる

今回やった構成

  • Expo(EAS)
  • Android アプリ
  • EAS Build + EAS Update
  • DeployGate で配布

iOSアプリだとApple Developerに登録が必要になるため今回は誰でも試せる構成にしています

実際にやった手順(概要)

  1. eas build --platform android --profile production
  2. アプリを DeployGate にアップロード
  3. JS を修正
  4. eas update --branch production -m "ota works finally"

この流れで preview update では確実に反映される状態になりました

詰まったポイント・ハマりどころ

OTA Updateされない原因

app.json
{
  "expo": {
  ...
    "owner": "roll1226",
    "runtimeVersion": "1"
  }
}

この設定の場合:

  • runtimeVersion が一致する限り
  • すべて同じ OTA Update の対象 になります

結果として:

  • update group の commit ID がすべて同じに見える
  • 何が更新されているのか分かりにくい

という状態になりました

実務的におすすめ:

app.json
{
  "expo": {
  ...
    "owner": "roll1226",
    "runtimeVersion": {
      "policy": "appVersion"
    }
  }
}
  • ネイティブコードが変わったら runtimeVersion を変える
  • JS だけなら OTA で吸収する

という運用がしやすくなります


自動更新を止め方

app.json
{
  "expo": {
    ...
    "updates": {
      "enabled": true,
      "checkAutomatically": "ON_LOAD",
      "fallbackToCacheTimeout": 0,
      "url": "https://u.expo.dev/xxxxxxxxxxxxxxxxx"
    },
    ...
  }
}

この設定だと:

  • アプリ起動時に自動で更新を確認
  • 条件次第で即反映される

だったので

app.json
{
  "expo": {
    ...
    "updates": {
      "enabled": true,
      "checkAutomatically": "NEVER",
      "fallbackToCacheTimeout": 0,
      "url": "https://u.expo.dev/xxxxxxxxxxxxxxxxx"
    },
    ...
  }
}
  • アプリ起動時に自動で更新しないように設定
  • 手動更新 UI を出したいのに勝手に更新される

という対応にしました


手動更新 UI を出す実装

考え方はシンプルで:

  1. 起動時に checkForUpdateAsync()
  2. 更新があればフラグを立てる
  3. ボタンで fetchUpdateAsync() + reloadAsync()

という流れです

const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
  setUpdateAvailable(true);
}

この実装をすることで

  • 自動更新はしない
  • アプリを開いている間に更新が来たら通知する

という挙動を実現できます


アプリ起動中に OTA が来たら通知

  • 定期的に checkForUpdateAsync() を呼ぶ
  • フォアグラウンド復帰時にチェックする

以下のようなアップデート通知 UI を表示することができます

まとめ

  • Expo OTA Update は 実務でも十分使える
  • ただし「何でも OTA」は危険
  • runtimeVersion の設計がかなり重要
  • 自動更新はオフ + 手動 UI が安心

OTA Update は強力ですが、ストア審査・ユーザー体験・運用ルールを意識して使うことが大切だと感じました

今回記事を書く時に書いたコードは下記になります

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?