React Nativeアプリのバグ修正やUI微調整を、ストア審査を通さずにユーザーへ即座に届けたい。そんなニーズに応えてきたのがCodePushです。

ただし2025年3月のApp Center終了により、CodePushを取り巻く環境は大きく変わりました。従来のApp Center CodePushはすでに利用できず、公式リポジトリもアーカイブ済みです。

本記事ではCodePushの基本的な仕組みから、2026年現在で選択できる代替サービスの比較、具体的な導入手順、ストアガイドラインへの対応まで一括して整理しています。

CodePushの仕組みとOTAアップデートの基礎

CodePushはMicrosoftが開発したOTA(Over-The-Air)アップデートの仕組みです。React Nativeアプリが内部で使っているJavaScriptバンドルとアセットファイルを、アプリストアを経由せずに端末へ直接配信できます。

OTAアップデートが可能な範囲

React Nativeアプリはネイティブコード(Objective-C/Swift/Java/Kotlin)とJavaScriptバンドルの2層で構成されています。CodePushで更新できるのはJavaScript層のみです。

更新可能更新不可(ストア申請が必要)
JavaScriptコード全般ネイティブモジュールの追加・変更
画像・フォントなどのアセットAndroidManifest.xml / Info.plist の変更
スタイル・レイアウトの修正ネイティブライブラリ(.so / .framework)の差し替え
ビジネスロジックの修正アプリアイコン・スプラッシュ画面の変更

配信の流れ

  1. 開発者がCLIからJSバンドルをCodePushサーバーにアップロード
  2. アプリ起動時(または設定したタイミング)にサーバーへ更新確認リクエストを送信
  3. 新しいバンドルが存在すれば差分をダウンロード
  4. 設定に応じて即座に適用、または次回起動時に適用

起動のたびに更新を確認する方式のほか、バックグラウンド復帰時にチェックする方式も選べます。ユーザー体験を損なわない柔軟な配信設計が可能です。

App Center終了とCodePushの現状(2026年2月時点)

Microsoft App Centerは2025年3月31日に正式にリタイアしました(出典: Microsoft Learn)。この日以降、App CenterへのサインインやAPIコールは利用できません。

なお、Analytics & Diagnostics機能のみ2026年6月30日まで延長されていますが、CodePush機能は延長対象外です。

公式リポジトリの状態

リポジトリ状態最終更新
microsoft/react-native-code-pushアーカイブ済み(read-only)v9.0.1(2024年12月)
microsoft/code-push-serverアーカイブ済み2025年5月
microsoft/code-pushアーカイブ済み2025年5月

microsoft/react-native-code-push v9.0.1はReact Native New Architecture(0.76以降のデフォルト)に非対応です。New Architectureを有効にしたプロジェクトでは動作しないため、注意が必要です。

Microsoftが公開したスタンドアロンサーバー

App Center終了に先立ち、Microsoftはcode-push-serverリポジトリでCodePushサーバーのソースコードを公開しました。Node.jsアプリケーションとして動作し、Azure Blob Storageが必要です。

ただしこのリポジトリも2025年5月にアーカイブされており、Microsoftによるサポートやissue対応は行われません。「as is」での提供であり、以降のメンテナンスはコミュニティに委ねられています。

CodePushの代替サービス比較

App Center終了後、複数の代替サービスが登場しています。プロジェクトの状況に応じて最適な選択肢が異なります。

サービス一覧と特徴

サービスNew Architectureサーバー管理料金目安(月額)特徴
Codemagic CodePush対応マネージド$99〜 / 10万MAUApp Center互換、CI/CD統合
Expo EAS Update対応マネージド無料〜$99+従量制Expoプロジェクト向け、ブランチ/チャネルモデル
@bravemobile/react-native-code-push対応セルフホストインフラ費用のみS3等で運用可能、APIサーバー不要
RevoPush対応マネージド$90〜 / 100万アップデートCodePush SDK互換、移行が容易
Hot Updater対応セルフホストインフラ費用のみOSSのOTAソリューション
Microsoft code-push-server非対応セルフホストAzure利用費用公式ソースだがアーカイブ済み

Codemagic CodePush

CI/CDツールとして知られるCodemagicが提供するCodePushのマネージドサービスです。App Center CodePushとSDKレベルで互換性があり、既存のCodePushクライアントからの移行負担が比較的軽いのが特長です。

主な仕様:

  • 月額$99から(MAU 10万人まで。アップデート回数・帯域幅は無制限)
  • 配信成功率99.9%、月間10億超のAPIリクエスト処理実績
  • SOC 2 Type 2、ISO 27001対応
  • React Native 0.76以降のNew Architectureに対応(@code-push-next/react-native-code-pushパッケージを使用)

参照: Codemagic CodePush

Expo EAS Update

Expoプロジェクトを使っている場合は、EAS Updateが最もスムーズな選択肢です。expo-updatesライブラリを通じてJSバンドルとアセットをOTAで更新できます。

仕組み:

  1. アップデートを「ブランチ」にアップロード(Gitブランチと似た概念)
  2. ビルド時に指定した「チャネル」にブランチを紐づける
  3. アプリ起動時にマニフェストを取得し、互換性のある最新アップデートをダウンロード
  4. Runtime Versionの完全一致で互換性を検証

料金:

プラン月額MAU上限
Free$01,000
Starter$193,000
Production$99 + 従量制50,000(超過分は従量制)

参照: Expo EAS UpdateExpo Pricing

@bravemobile/react-native-code-push

韓国のSoomgo社(Brave Mobile)が開発・メンテナンスしているmicrosoft/react-native-code-pushのフォークです。2026年2月時点でも活発に更新されており、最新バージョンはv12.3.1です。

microsoft公式との比較:

項目microsoft公式(v9.0.1)@bravemobile(v12.3.1)
メンテナンスアーカイブ済み活発に更新中(最終push: 2026年2月)
New Architecture非対応対応
React Native対応〜0.750.74〜0.84
サーバー要件App Center(終了済み)S3等の静的ホスティングのみで運用可能
デプロイメントキー必要不要
Expo対応なしSDK 50.0.0以降

code-push.config.tsbundleUploadergetReleaseHistoryを設定することで、追加のAPIサーバーなしにAWS S3やCloudflare R2などの静的ストレージだけで運用できます。

参照: Soomgo-Mobile/react-native-code-push(GitHub)

選定フローチャート

  • Expoプロジェクト → EAS Update
  • 非Expoで管理コスト最小化 → Codemagic CodePush
  • 非Expoでインフラ自前管理 → @bravemobile/react-native-code-push
  • CodePush SDK互換で手軽に移行 → RevoPush

CodePushの導入手順(Codemagic版)

2026年現在、新規にCodePushを導入する場合はCodemagic CodePushが現実的な選択肢の一つです。以下にセットアップの流れを示します。

1. パッケージのインストール

New Architecture対応版のパッケージを使用します。

# npm
npm install @code-push-next/react-native-code-push

# yarn
yarn add @code-push-next/react-native-code-push

2. iOSの設定

ios/Podfileで依存関係をインストール後、AppDelegateを編集します。

// AppDelegate.mm
#import <CodePush/CodePush.h>

// sourceURLForBridge メソッド内
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [CodePush bundleURL];
#endif
}

Info.plistにデプロイメントキーを追加します(Codemagicダッシュボードで取得)。

<key>CodePushDeploymentKey</key>
<string>YOUR_IOS_DEPLOYMENT_KEY</string>

3. Androidの設定

android/app/build.gradleにCodePushの設定を追加します。

// build.gradle (app)
apply from: "../../node_modules/@code-push-next/react-native-code-push/android/codepush.gradle"

MainApplicationでバンドルURLをCodePush経由に切り替えます。

// MainApplication.java
import com.microsoft.codepush.react.CodePush;

@Override
protected String getJSBundleFile() {
    return CodePush.getJSBundleFile();
}

strings.xmlにデプロイメントキーを設定します。

<string moduleConfig="true" name="CodePushDeploymentKey">YOUR_ANDROID_DEPLOYMENT_KEY</string>

4. ルートコンポーネントのラッピング

import codePush from '@code-push-next/react-native-code-push';

const codePushOptions = {
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
  installMode: codePush.InstallMode.ON_NEXT_RESUME,
};

function App() {
  return (
    // アプリのコンポーネント
  );
}

export default codePush(codePushOptions)(App);

5. アップデートの配信

Codemagic CLIまたはApp Center CLI互換コマンドで配信します。

# Staging環境へリリース
appcenter codepush release-react -a <owner>/<app-name> -d Staging

# Production環境へプロモート
appcenter codepush promote -a <owner>/<app-name> -s Staging -d Production

アップデート戦略の設計

CodePushでは「いつ確認するか」と「いつ適用するか」を組み合わせてアップデート戦略を構築します。

確認タイミング(CheckFrequency)

動作適したケース
ON_APP_STARTアプリ起動時に毎回確認重要な修正を素早く届けたい場合
ON_APP_RESUMEバックグラウンドから復帰時に確認一般的な用途に最適
MANUAL開発者が明示的に呼び出し独自のUI/UXで制御したい場合

適用タイミング(InstallMode)

動作ユーザー体験
IMMEDIATEダウンロード完了後すぐ再起動して適用一瞬アプリが再起動する
ON_NEXT_RESTART次回アプリ起動時に適用ユーザーは気づかない
ON_NEXT_RESUME次回バックグラウンド復帰時に適用ユーザーは気づきにくい
ON_NEXT_SUSPENDバックグラウンドに移行する際に適用完全にサイレント

推奨パターン

サイレントアップデート(推奨):

const codePushOptions = {
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
  installMode: codePush.InstallMode.ON_NEXT_RESUME,
  minimumBackgroundDuration: 60 * 10, // 10分以上バックグラウンドにいた場合
};

この設定ではユーザーがアプリを一定時間バックグラウンドに置いた後に復帰すると、自動で最新バンドルが適用されます。操作中に再起動が入らないため、体験を損ないません。

緊急修正用(強制アップデート):

const codePushOptions = {
  checkFrequency: codePush.CheckFrequency.ON_APP_START,
  installMode: codePush.InstallMode.IMMEDIATE,
  mandatoryInstallMode: codePush.InstallMode.IMMEDIATE,
};

セキュリティ修正やクリティカルバグの場合に使います。配信コマンドに--mandatoryフラグを付けることで、ユーザーに強制適用できます。

ロールバックとヘルスチェック

CodePushにはアップデート失敗時の自動ロールバック機構が備わっています。

自動ロールバック

新しいバンドルを適用した直後にアプリがクラッシュした場合、CodePushは自動的に前のバンドルに戻します。これにより、不具合のあるアップデートが配信されても端末が使えなくなる事態を防げます。

手動ロールバック

CLIから特定のリリースをロールバックすることも可能です。

appcenter codepush rollback -a <owner>/<app-name> -d Production

プログラムによるヘルスチェック

アップデート適用後に独自の検証ロジックを実行し、問題があればロールバックするパターンです。

codePush.sync(
  {
    installMode: codePush.InstallMode.ON_NEXT_RESTART,
  },
  (status) => {
    switch (status) {
      case codePush.SyncStatus.UPDATE_INSTALLED:
        // ヘルスチェック実行
        runHealthCheck().then((isHealthy) => {
          if (isHealthy) {
            codePush.notifyAppReady();
          } else {
            codePush.restartApp(); // 前のバージョンに戻る
          }
        });
        break;
    }
  }
);

codePush.notifyAppReady()を呼ばないとCodePushはアップデートを「失敗」と判定し、次回起動時に前のバンドルへ自動ロールバックします。この仕組みを活用してAPI疎通チェックやクリティカルな画面の描画確認を挟むことで、配信の安全性を高められます。

Staging・Productionのデプロイ環境

CodePushはデフォルトでStagingProductionの2つのデプロイ環境を提供します。

運用フロー

  1. まずStagingへリリースし、社内テスト端末で動作確認
  2. 問題なければProductionへプロモート
  3. 段階的ロールアウトでユーザーの一部に先行配信
# Stagingに配信
appcenter codepush release-react -a owner/MyApp -d Staging

# 内部テスト後、Productionへプロモート
appcenter codepush promote -a owner/MyApp -s Staging -d Production

# 段階的ロールアウト(25%のユーザーに先行配信)
appcenter codepush release-react -a owner/MyApp -d Production --rollout 25

段階的ロールアウトではクラッシュ率の急増がないかを確認してから、100%に拡大できます。本番環境への配信リスクを大幅に低減できる手法です。

Apple / Google ストアガイドラインへの準拠

CodePush(OTAアップデート)を利用する上で、各ストアのガイドラインを遵守することは必須です。

Apple(Developer Program License Agreement セクション 3.3.1.B)

Apple Developer Program License Agreementのセクション3.3.1.Bでは、インタープリテッドコード(Interpreted code)のダウンロードと実行が一定の条件下で許容されています。

許容される条件:

  • (a) アプリの主要な目的・機能を、App Storeに提出した意図と異なる形に変更しないこと
  • (b) 別のコードやアプリケーションのためのストア・ストアフロントを作成しないこと
  • (c) OSの公式APIやビルトインフレームワークを迂回するセキュリティ機能・署名・サンドボックス回避を行わないこと

React NativeのJSバンドルはインタープリテッドコードに該当するため、上記の条件を遵守する限りOTAアップデートは許容されています。

参照: Apple Developer Program License Agreement

Google Play(Device and Network Abuseポリシー)

An app distributed via Google Play may not modify, replace, or update itself using any method other than Google Play’s update mechanism. Likewise, an app may not download executable code (e.g. dex, JAR, .so files) from a source other than Google Play. This restriction does not apply to code that runs in a virtual machine and has limited access to Android APIs (such as JavaScript in a webview or browser).

JavaScriptCore(またはHermes)上で動くJSバンドルは仮想マシン/インタープリタ上のコードとして例外に該当します。

禁止事項:

  • .dex、.jar、.soファイルの外部からのダウンロード・差し替え
  • ネイティブバイナリの動的ロード

参照: Google Play Developer Program Policy

実務上のポイント

バグ修正、UI調整、テキスト変更、ビジネスロジックの修正といった範囲であれば、両ストアのガイドラインに抵触するリスクは低いです。ただし、OTAでアプリの機能を根本的に変えてしまうような更新(例: 電卓アプリをゲームに変えるなど)はガイドライン違反となります。

テストとデバッグ

Staging環境でのテスト手順

  1. テスト端末のアプリをStaging用デプロイメントキーでビルド
  2. CLIからStaging環境へアップデートを配信
  3. アプリを起動(または復帰)して更新が適用されることを確認
# Staging環境のデプロイ状況を確認
appcenter codepush deployment list -a owner/MyApp --displayKeys

デバッグビルドでの確認

Releaseビルドでのみ動作する点に注意が必要です。デバッグビルドではMetroバンドラーからJSを取得するため、CodePushは無効になります。

テスト時はReleaseビルドを作成して実機で検証してください。

# iOSのReleaseビルド
npx react-native run-ios --mode Release

# AndroidのReleaseビルド
npx react-native run-android --variant release

CodePushキャッシュのクリア

テスト中に古いバンドルがキャッシュされて新しいアップデートが反映されない場合は、アプリのデータを削除するかアプリを再インストールします。

運用上の注意点と実践的なTips

セマンティックバージョニングの徹底

アプリのバイナリバージョン(1.2.0など)とCodePushのターゲットバージョンが一致していないと、アップデートが配信されません。package.jsonのバージョンとネイティブ側のバージョン(Info.plistCFBundleShortVersionStringbuild.gradleversionName)を必ず揃えてください。

リリースノートの付与

配信時に--descriptionでリリースノートを付けておくと、後から配信履歴を追跡しやすくなります。

appcenter codepush release-react -a owner/MyApp -d Staging \
  --description "ログイン画面のバリデーション修正"

Error Boundaryとの併用

CodePushでJSバンドルを更新した後にクラッシュが発生すると自動ロールバックが作動しますが、React側のError Boundaryを併用すると、クラッシュしない範囲のエラー(表示崩れ等)もキャッチしてフォールバックUIを表示できます。

import React from 'react';

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error) {
    // エラーレポートサービスに送信
    reportError(error);
  }

  render() {
    if (this.state.hasError) {
      return <FallbackUI />;
    }
    return this.props.children;
  }
}

バンドルサイズへの配慮

CodePushは差分ダウンロードに対応していますが、JSバンドル全体が大きいと初回の差分計算に時間がかかります。react-native-bundle-visualizerなどでバンドルサイズを定期的に確認し、不要な依存関係を削除することを推奨します。

Flutter向けOTA:Shorebird

React Native以外のクロスプラットフォームフレームワークであるFlutterでも、同様のOTAアップデート需要があります。FlutterにはCodePush相当のサービスとしてShorebirdが存在します。

Shorebirdはパッチベースの差分更新を採用しており、バンドル全体ではなく変更部分のみを配信します。月額$20のProプラン(5万パッチ配信含む)から利用可能で、無料のHobbyプランもあります。

参照: ShorebirdShorebird Pricing

React NativeとFlutterのどちらを採用するかを検討している段階であれば、OTAアップデートのエコシステムも判断材料の一つになります。

まとめ

CodePushはReact NativeアプリにおけるOTAアップデートの先駆的な仕組みですが、App Centerの終了と公式リポジトリのアーカイブにより、従来のMicrosoft公式パスはすでに使えません。

2026年現在の選択肢を整理すると次のとおりです。

  • Expoプロジェクト → EAS Updateが標準。ブランチ/チャネルモデルで柔軟に配信を管理できます
  • 非Expoでマネージドサービスを使いたい → Codemagic CodePushがApp Center互換で移行負担が少なく、New Architectureにも対応しています
  • インフラを自前で管理したい → @bravemobile/react-native-code-pushがS3だけで運用でき、APIサーバーが不要です

どのサービスを選んでも、ストアガイドラインの範囲内でJSバンドルのOTAアップデートを行うことは許容されています。Staging→Productionの段階的なデプロイフロー、自動ロールバック、ヘルスチェックの仕組みを組み合わせて、安全な配信体制を構築してください。