メインコンテンツへスキップ

CapacitorJSアプリのOTAアップデートを正しく行う方法

Capgo を使用して CapacitorJS および Electron アプリを OTA アップデートする方法を学びましょう。セットアップ、署名、チャンネル、CI/CD、テスト、ロールバックを網羅した実践的なガイドです。

CapacitorJSアプリのOTAアップデートを正しく行う方法

金曜の午後にチェックアウトのデグレが見つかりました。修正はすでに Capacitor の Web レイヤーに入っていますが、App Store の審査が終わるまであと3日かかります。Android ユーザーならより早く新しいパッケージを受け取れますが、JavaScript の修正だけで全ユーザーにネイティブビルドの再インストールを強いるのはやはり無駄です。

これこそが、チームが CapacitorJS アプリの OTA アップデート方法を学ぶ実用的な理由です。制御された OTA リリースなら、署名済みの Web bundle を対象となるインストール済みバイナリに配信し、バックグラウンドでダウンロードして次回起動時に適用できます。ネイティブの変更は引き続きストアのプロセスに従います。難しいのはファイルのアップロードではありません。バージョンターゲティング、署名、ロールアウト制御、オブザーバビリティ、リカバリを、稼働中のデバイス群全体でいかに整合させるかです。

目次

CapacitorJS チームにとって OTA が重要な理由

Capacitor アプリは通常、2つのリリース対象を持っています。ネイティブバイナリには、プラットフォームシェル、権限、プラグイン、アイコン、entitlements、その他ストア審査の対象となる機能が含まれます。ウェブレイヤーには、JavaScript、CSS、HTML、ルーティング、文言、アセットが含まれます。OTAアップデートは2つ目のレイヤーを対象とするため、変更が以下で説明するプラットフォームとストアポリシーの境界内に収まる限り、ネイティブシェルを再ビルドせずに壊れたチェックアウトフローを修正できます。 Capgo OTAガイドライン.

ストアの遅延と即時修正を比較して、OTAアップデートの重要性を示す図。

運用上のメリットはスピードだけではありません。インストール済みのバイナリは足並みを揃えて更新されるわけではありません。古いネイティブビルドを起動するユーザーもいれば、最新のストア版を使うユーザーもおり、バイナリごとにウェブバンドルから利用できるネイティブAPIが異なる場合があります。サポートされていないネイティブ API 向けにコンパイルされたバンドルは、JavaScriptの差分が有効でも失敗する可能性があります。そのためOTAは、リリースエンジニアリングを回避する近道ではなく、互換性システムです。

アップデーターをデリバリーパイプラインとして扱う

本番環境のセットアップには、明確な手順が必要です:

  1. ネイティブブリッジをインストールする: updaterパッケージを追加し、Capacitor を同期してiOSとAndroidに認識させます。
  2. バンドルに署名する: 署名用マテリアルはリポジトリの外で管理し、検証をクライアントパスの一部として組み込みます。
  3. チャンネルを指定する: staging、beta、production、または顧客固有のグループを意図的にルーティングします。
  4. 配信を自動化: テストがパスした後にのみ、CIでビルド、署名、アップロード、プロモーションを実行します。
  5. 採用状況を監視: チャネルとバイナリごとに、ダウンロード、インストール、起動、クラッシュ、ヘルスシグナルを追跡します。
  6. 迅速なロールバック: 既知の正常なバンドルをサーバーサイドで復元し、クライアントサイドの復旧保護を維持します。

Capgo はこのワークフローの選択肢の一つです。そのオープンソースの Capacitor アプデーターとクラウドサービスは、署名付きの Web バンドルを対象チャネルに公開し、次回起動時に適用し、バージョンおよびデバイスレベルの配信情報を公開します。可用性とリリースのレジリエンスを評価しているチームは、さらに以下を確認できます。 Capacitor アプリの可用性.

実践的なルール: バンドルがどのネイティブバイナリを対象としているか特定できない場合、そのバンドルを本番環境に昇格させないでください。

OTA が成功するのは、Web code とネイティブ code の境界を隠さずに、不要なストアリリースを削減できる場合です。問題は、チームがバンドルをプッシュできるかどうかではありません。誰が受信したか、なぜ対象だったか、起動後に何が起きたか、バンドルが異常をきたした場合にサービスをどのように復旧するかを説明できるかどうかです。

前提条件と Capgo アップデーターのインストール

ターミナルを開く前に、プロジェクトとリリース用アカウントの準備ができているか確認してください。必要なものは、初期化済みの Capacitor 5 または 6 アプリケーション、 @capacitor/cli Node 18 以降、ターゲットバイナリ用の有効な Apple Developer アカウントと Google Play Console アカウント、Capgo クラウドアカウント appId および API キーです。

最初のインストールは、意図的に最小限の構成になっています:

npm install @capgo/capacitor-updater
npx cap sync
npx @capgo/cli init

npm install JavaScript パッケージとネイティブ依存関係を追加します。 npx cap sync 多くの人がスキップしがちなステップですが、これを怠るとネイティブブリッジがリンクされません。JavaScript レイヤーはコンパイルできても、実行時にインストール済みバイナリ内に存在しないブリッジを呼び出そうとしてしまいます。インストール後、およびネイティブプラグインの設定を変更した際には、必ず同期を実行してください。

イニシャライザは、あなたの設定ファイルを capacitor.config.ts アップデーター設定、Web エンドポイント、デフォルトチャンネルでパッチします。パッチをそのまま受け入れるのではなく、ファイルを開いてアプリの識別情報とアップデート契約を明示的に確認してください:

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  version: '1.0.0',
  autoUpdate: true,
  updateUrl: '',
  capgo: {
    channel: 'staging'
  }
}

生成される正確な構造は、プロジェクトや CLI のバージョンによって異なる場合がありますが、重要な値は同じです。 appId は、インストール済みバイナリと一致する必要があります。 version は、ネイティブビルドとの関係を記述する必要があります。 autoUpdate 起動ポリシーを反映している必要があり、 updateUrl バイナリが信頼するサービスを指している必要があり、 capgo ブロックで初期チャネルを特定する必要があります。

リリースビルド前の検証

XcodeやAndroid Studioを開く前に、次の診断コマンドを実行してください:

npx @capgo/cli doctor

正常な結果では、CLI が利用可能であること、プロジェクト設定が読み取れること、updaterパッケージが検出されること、必要なアプリケーション識別子が存在すること、認証が設定済みのアカウントに到達できることが確認されるはずです。native syncの欠如、アプリIDの不在、updater設定の無効が報告されることはありません。

https://capgo.app/docs/img/cli-doctor.png のスクリーンショット

最初のNative Buildは、あえて極力シンプルに保ってください。実機のiOSデバイスとAndroidデバイスにインストールし、ネットワークに接続した状態で起動、一度終了して再度開き、通常の起動経路に影響を与えずにupdaterがチェックできることを確認します。 Capacitor updaterのインストールワークフロー プロジェクト設定を期待されるプラグイン構成と比較する際に役立ちます。

最初のOTA Bundleを安全に配信する

最初のバンドルは機能リリースではなく、リリースパスのテストとして扱ってください。アーティファクトを準備する前に、署名キーを作成またはローテーションしてください。

npx @capgo/cli key create

秘密鍵はシークレットマネージャーに保管してください。コミットしたり、プロジェクトアーカイブに保存したり、CI出力に露出させたりしないでください。ネイティブの信頼パスには公開検証情報が必要です。秘密鍵にアクセスできるのは署名ジョブのみであるべきです。

JavaScript側のバージョンを package.json またはWebリリースメタデータに変更してください。Web限定の修正では、ネイティブのバージョンフィールドは変更しないでください。OTAバンドルはネイティブのcodeを追加したり、インストール済みバイナリが宣言した機能を変更したりできないため、ネイティブバージョンを変更しても互換性が向上するわけではなく、むしろ混乱を招くだけです。

署名済みアーティファクトを意図したチャネルにアップロードしてください:

npx @capgo/cli bundle upload --channel production

アップロードの成功は、サーバーがリクエストを受け付けただけを示します。コマンドの出力を読み、bundle識別子、ターゲットのネイティブバージョン制約、署名付きチェックサム、およびチャネル割り当てを確認してください。これらのフィールドは成果物を特定し、インストールされたバイナリがそれを受信できるかどうかを示します。

ダッシュボードをリリースゲートとして活用する

bundle詳細ビューでは、リリースに関する4つの質問に答える必要があります:

  • 最小ネイティブバージョン: このbundleを実行できる最も古いバイナリはどれですか?
  • 最大ネイティブバージョン: 意図的に除外される新しいバイナリはどれですか?
  • チャネル: どのオーディエンスが成果物を見つけられますか?
  • ロールアウト率: その対象オーディエンスのうち、どれくらいの割合が受信できますか?

本番環境での公開は 5%、次に拡張に必要な証拠を定義します。ダウンロードとインストールの成功、正常なコールドスタート、クラッシュフリーセッション、変更したフローでの JavaScript エラーを確認します。Capgo ダッシュボードでは、アーティファクトの識別情報と配信コントロールを一緒に確認できるようにしておきます。

https://capgo.app/docs/img/bundle-detail.png のスクリーンショット

デバイス上の経路を実際に動かすには、デバッグビルドを使用します。 getCurrent() アクティブなバンドルを報告し、 notifyAppReady() 新しいバンドルが正常な状態に達したことを確認します:

import { CapacitorUpdater } from '@capgo/capacitor-updater'

const current = await CapacitorUpdater.getCurrent()
console.log(current)

await CapacitorUpdater.notifyAppReady()

readiness を呼び出すのは、アプリがヘルスチェックを通過できる程度に初期化されてからにしてください。readiness が確認されない場合、次回のコールドスタート時に自動リカバリが bundle を失敗としてマークする可能性があります。このセーフガードは本番ユーザーを守りますが、不完全なテストが配信の問題のように見えることもあります。展開範囲を広げる前に、テストデバイスごとにアクティブな bundle と起動結果を記録してください。

Channels、Rollouts、CI/CD自動化

Channel は、公開された bundle とアプリをインストールしたデバイスをつなぐルーティングレイヤーであり、リリースゲートでもあります。staging channel は既知の native binary を指し、beta channel は管理されたコホートに配信し、production は前段の channel がスモークテストを通過してから初めて移行するようにしてください。

明示的な名前でステージングパスを作成します:

npx @capgo/cli channel create staging
npx @capgo/cli bundle assign <bundle-id> --channel staging

そのチャンネルを、テスト端末で使用しているネイティブバージョンに固定してください。テスターは、追加のプラグインや異なる設定を含むローカル開発ビルドではなく、本番環境がサポートするのと同じバイナリを実行すべきです。スモークスイートに合格したら、わずかに異なる2つ目のbundleをアップロードするのではなく、テスト済みのアーティファクトを昇格させてください。

チャンネルマップは以下に配置し、 capgo.config.json アプリケーションの code と同様にレビューされるべきです。チャンネル名は安定させ、想定されるネイティブ互換性の範囲を明確にし、本番への昇格を明示的なCIアクションにしてください。機能の露出を配信の露出と併せて管理するチームにとって、これらの フィーチャーフラグ管理のヒントは、 デプロイ権限とユーザー向けの有効化を分離するための有用な方法を提供します。

プロモーションをCIに連携させる

実用的な GitHub Actionsの設計には、2つのパスがあります:

  • プルリクエスト: Webレイヤーをビルドし、制限付きのプレビュー用クレデンシャルで署名して、一時的なプレビューチャンネルに公開します。プルリクエストが閉じられたら、そのチャンネルを削除するか期限切れにしてください。
  • タグ付けされたmainリリース: ユニットテストを実行し、本番用bundleをビルドして、そのネイティブバージョン制約を検証し、アップロードします。テストジョブが正常終了した場合にのみ、昇格させてください。

プロモーションコマンドの例は以下の通りです:

npx @capgo/cli bundle promote <bundle-id> \
  --to-channel production \
  --percent 5

たとえば次のように段階的に露出を増やします: 25%、50%、100%各ステップの間には、CIでの承認や監視ジョブを挟みます。パーセンテージやコマンドは制御手段であり、安全性の証拠ではありません。ビルドが通ることは、bundleの構文が正しいことを示すだけです。特定のネイティブバイナリ上で、永続化されたローカル状態、低速な接続、古いセッションから復帰したデバイスといった条件下でどう動作するかまでは示しません。

リリースの境界線: Web bundleはバイナリ互換性ウィンドウに属します。Channelは、インストール済みのアプリに含まれないネイティブAPIを参照するcodeを配信する抜け穴になってはいけません。

各bundleを、ビルド対象となった正確なネイティブバージョンに紐付けることで、TestFlightやAndroidの内部トラックビルドとの整合性を保ちます。ネイティブビルドが変わった場合は、互換性をターゲットにした新しいbundleを公開するか、新しいChannelマッピングを作成してください。 Capgo GitHub Actions 連携ガイド そのポリシーを再現可能なワークフローのステップに落とし込むのに役立ちます。

ソフトウェアChannelと自動化の3ステップを示す図:Staging Channel、Pin Binary、CI/CD Auto-Deploy。

テスト戦略と自動ロールバック

OTAリリースは、CIを通過してもアクティベーション後に失敗することがあります。その失敗は、bundle、ネイティブバイナリ、デバイスに保存された状態、あるいはネットワーク条件に依存する可能性があります。シミュレーターは画面が描画されることを確認できても、すべてのインストール済みバイナリを網羅したり、起動失敗時に正常に復旧できるかまでは示せません。

3つのテスト層を活用しましょう:

  1. CIでのbundleテスト: ユニットテスト、型チェック、lint、本番用Webビルドを実行します。単なるコンパイル確認で止めず、変更したチェックアウト、認証、ナビゲーション、永続化のパスを実際に動かして検証してください。
  2. プライベートデバイスチャネル: 以前のネイティブバイナリを実行している実機でプライベートチャネルをシードします。両プラットフォーム、クリーンインストール、アップグレードインストール、代表的な保存状態をカバーしてください。
  3. 本番カナリア: 少数の対象ユーザーから開始し、クラッシュレポートの連携とJavaScriptエラーのアラートを設定します。起動失敗は緊急事態として扱ってください。影響を受けたユーザーは、アプリ内エラーを報告するcodeに到達できない可能性があるためです。

この Capacitor OTAテストガイド テストの仕組みを解説します。運用ルールはシンプルです。各アップデートは、それが保護対象とするネイティブバイナリに対してテストしてください。

サーバー制御とクライアント復旧を切り離す

サーバーサイドのロールバックで新規ダウンロードを停止:

npx @capgo/cli channel set production --bundle <previous-id>

これにより、対象デバイスが次に検出する内容が変わります。すでにダウンロード済み、または各デバイスでアクティブなbundleが消えるわけではないため、クライアント側にもリカバリ制御が必要です。正常動作が確認済みのフォールバックを保持し、定義した起動失敗条件を満たしたら切り戻すようにupdaterを設定してください。

信頼性の高いリカバリパスには以下が含まれます:

  • ダウンロード失敗のトラッキング: 接続の問題と無効なアーティファクトを区別します。
  • インストール失敗のトラッキング: 展開、検証、ファイルシステムの問題を検知します。
  • 起動状態のトラッキング: アクティベーション後にアプリが使用可能な状態になったことを確認します。
  • 自動フォールバック: 起動が繰り返し失敗する場合は、以前の正常動作が確認済みのbundleを復元します。
  • 手動エスカレーション: サポートやエンジニアリングのために、デバイスおよびbundleの識別子を保持します。

大規模なデバイス群では、わずかな失敗率でも大きなサポート負荷を生みます。 OTA更新の成功率99.95%でも、100万台あたり約1,000件の失敗を意味します、出典: IoTフリート向けのOTAテストベンチマーク。同じソースでは、30分以内のロールバック、クラッシュ率0.1%未満、サポート対象期間内のデバイスが98%以上といったガードレールも説明されています。これらはベンチマークの例として扱い、普遍的な受入基準としないようにしてください。アプリのリスクとユーザーへの影響に基づいてエラーバジェットを設定してください。

署名、セキュリティ、OTAで変更できないもの

署名のない更新は、配信エンドポイントをサプライチェーン攻撃の対象にします。TLSは接続を保護しますが、クライアントはダウンロードされた成果物が承認されたリリースプロセスからのものであり、転送中に置き換えや改ざんされていないことを確認する必要があります。

アップデータツールでEd25519鍵ペアを生成します。秘密鍵はCIシークレットに保存し、アプリのビルド時にパブリック検証鍵をネイティブバイナリに埋め込みます。クライアントはアクティベーション前にすべてのバンドルを検証する必要があります。CLI トークンは環境と権限スコープで制限し、アップロードとプロモーションのログを保持し、本番環境の操作には強力な認証を必須にしてください。

キーローテーションは、単なる設定変更ではなく、互換性を維持するための移行として捉えてください。まず新しいキーを生成し、現在の公開鍵と新しい公開鍵の両方を信頼する Native Build を配信します。その後、新しい秘密鍵でリリースに署名します。古いキーの削除は、互換性のあるネイティブバイナリが新しいキーを採用した後に行ってください。早すぎるタイミングで信頼を解除すると、古いバイナリが有効なアップデートを受け取れなくなります。漏洩したキーを無期限に信頼し続けると、ローテーションの意味がなくなります。

リリース計画で境界を引く

OTA は Web レイヤーの変更を扱います。インストール済みのバイナリにない機能に依存する変更には、ネイティブリリースが必要です:

カテゴリ OTA で配信可能 ネイティブリリースが必要
アプリケーションの動作 JavaScript のロジック、ルーティング、バリデーション、状態管理 ネイティブプラグインの実装
表示 CSS、HTML、テキスト、テーマトークン、互換性のある画像アセット アプリのアイコンおよびスプラッシュ画面のリソース
プラットフォームへのアクセス バイナリに既にある機能への既存の Capacitor Web レイヤー呼び出し 新しい権限、エンタイトルメント、またはネイティブ API
設定 互換性のある Web 設定とリモートコンテンツルール Info.plist, AndroidManifest.xml、署名 ID
ストアメタデータ ストア審査の対象となる動作やバージョンメタデータを変更するものはない ストアポリシーに影響するメタデータとバージョン番号の変更

この Capacitor アプデーター code署名ドキュメント 検証モデルを説明しています。改ざん検知可能な監査ログ、証明書検証、TLS、厳格なアクセス制御、およびバージョン偽装や鍵漏洩時の調査プロセスを運用に適用してください。

インストール済みのネイティブ環境の分布は徐々に変わるため、互換性ターゲットの設定は依然として重要です。Appleの報告によると、 全アクティブデバイスの66%がiOS 26を利用しており、 と 過去4年間に発売されたデバイスでは74%がiOS 26です。一方、別のレポートではiOS 26の割合を サイクル後半時点の全デバイスの79%としており、 モバイルOTAのキー管理に関する研究でまとめられています。これらの数値は調査時点や対象デバイスが異なりますが、実用的な結論は一貫しています。成熟したプラットフォームでも、すべてのデバイスが一度にアップデートされるわけではありません。単一のOTAアーティファクトが全デバイスに適合すると仮定せず、ネイティブのバージョンと機能に基づいてbundleを割り当ててください。

リリース前の運用チェックリスト

リリースチェックリストは1ページに収め、リポジトリやrunbookと一緒に保管してください。インシデントのたびに更新してください。実際の障害後に追加したコントロールは、通常、次の再発を防ぎます。

アップロード前

  • 互換性の確認: bundleが正確なnative binaryをターゲットにしており、利用できないplugin APIを使用していないことを確認してください。
  • アーティファクトの確認: クリーンなワークスペースからbuildし、生成されたファイルを確認して、意図したWebバージョンであることを検証してください。
  • 署名の保護: CIに想定どおりのsecretとkeyが設定されていること、logsが機密情報を露出しないことを確認してください。
  • チャネルの検証: bundleを割り当てる前に、staging、beta、productionのマッピングをレビューしてください。
  • リカバリ手段の確保: 以前の正常なbundleを記録し、フォールバックパスが引き続き機能することを確認してください。
  • 実機でのスモークテスト: 代表的なデバイスで、起動、ログイン、チェックアウト、ナビゲーション、永続化、updateの準備状況をテストしてください。

プロモーション中

まず限定ユーザーグループにリリースし、ユーザー影響に関連するシグナルを確認します:

  • クラッシュフリーセッション: 前のbundleと比較し、リグレッションを調査します。
  • JavaScriptエラー率: bundle、ネイティブバージョン、プラットフォーム、機能パスごとにエラーをグループ化します。
  • コールドスタートの挙動: アクティベーションで起動が変わったり、ユーザーが白画面のままにならないか確認します。
  • 機能カバレッジ: リモートで有効化された機能が、それを受け取るバイナリと一致しているか確認します。
  • 採用率と失敗: 更新チェックを行っていない対象デバイスと、チェックして失敗したデバイスを区別します。

プロモーション後の最初の観察期間を 30分 保持し、その後で露出範囲を広げてください。クリティカルパスが壊れた場合は、本番チャネルを前のバンドルにロールバックし、ログを保存した上で、修正を別のOTAバンドルで行うべきか、新しいネイティブリリースで行うべきかを判断してください。

リリース日の規律: フォールバックバンドルは、チームがその識別子、互換性範囲、復元コマンドを知っている場合にのみ役立ちます。

このチェックリストを共有オペレーションcodeとして扱ってください。Capgoは、署名済みバンドルの配信、チャネルターゲティング、ロールアウト制御、更新履歴、デバイスレベルのオブザーバビリティを提供できます。互換性ポリシーとプロモーションの決定は、引き続きチームが所有します。


Capgoは、CapacitorJSチームに、署名済みJavaScript、CSS、設定、アセットの更新に対する制御されたパスを提供します。チャネル、段階的配信、ロールバック保護、リリースオブザーバビリティを備えています。このチェックリストを次のデプロイに組み込み、ステージングバイナリに対してテストし、評価してください Capgo 本番ワークフローのために。

Capacitor アプリ向けの Live Updates

Web レイヤーのバグが本番で発生したら、App Store の審査を何日も待たずに Capgo で修正を配信しましょう。ネイティブの変更は通常の審査フローに残したまま、ユーザーはバックグラウンドでアップデートを受け取れます。

最新のブログ記事

Capgoは、真にプロフェッショナルなモバイルアプリを作るために必要な最高のインサイトを提供します。