OTA 更新パッケージをスリムで高速に保つ方法

より小さなバンドル、賢いリリース戦略、そして OTA 更新の通信量を抑える実践的なテクニックで、React Native ユーザーに OTA 更新をより速く届ける。

日本語
コピー
How to keep your OTA updates lean and fast

PR をマージして数分後、重要な修正が全ユーザーの手元に届く。修正からユーザーの指先まで一直線で、承認フローもなく、ユーザー体験を中断させることもない。この感覚には何度味わっても慣れない。

EAS Update はそれを可能にする。一度体験してしまうと、これなしでどう働いていたのか想像しにくくなる。だが、修正を配信することは物語の半分でしかない。ユーザーが恩恵を受けるのは、更新が実際に端末上で動いてからだ。ダウンロードが速ければ速いほど修正は早く届き、更新パッケージが小さければ小さいほど全員の体験が良くなる。ダウンロードは速く、コストは低く、チームとユーザーが増えても滑らかに。このガイドでは、更新を小さく保ち、安心して配信し、プッシュのたびに最大限の効果を得る方法を説明する。

EAS Update の課金方法をおさらい

EAS Update を使いこなすには、まず更新の配信と課金を決める 2 つの概念を理解しておくと役立つ。月間アクティブユーザー(MAU)と帯域幅だ。これらの仕組みと、更新をより小さくするためにできることを把握すれば、ユーザーのダウンロードは速くなり、コストは下がる。本記事は、EAS Update とは何か、そしてどのような場面に適しているかをすでに知っている読者を想定している。

月間アクティブユーザー(MAU)

月間アクティブユーザー(MAU)とは、1 つの請求サイクルの中で EAS Update 経由で少なくとも 1 回更新をダウンロードしたユニークユーザーを指す。その月に何回更新をダウンロードしたとしても、カウントは 1 MAU だ。ユーザーが更新を確認したものの、ダウンロードできる新しいバージョンがなかった場合(つまりダウンロードが発生しなかった場合)は、まったくカウントされない。

アプリをアンインストールして再インストールすると、次に更新をダウンロードした時点で新しい MAU としてカウントされる。同様に、同じ人物が 2 台の異なる端末を使えば 2 MAU になる。こうしたエッジケースで数字が大きく動くことはまずないが、実際の MAU 数が Play や App Store の統計、あるいはより多くのユーザー識別情報を考慮する指標と食い違う場合は、知っておく価値がある。

帯域幅

ユーザーが更新をダウンロードするたびに帯域幅を消費するが、各プランの枠はかなり余裕があり、ほとんどのチームの使用量はプランの範囲に収まっている。圧縮などのおかげで、実際の帯域幅消費は想像よりずっと少ないことが多い。

ダウンロードサイズは何を変更したかで決まる。たとえば JavaScript だけを更新したなら、ユーザーがダウンロードするのはその部分だけだ。元のビルド(または前回の更新)で端末にすでに入っているアセットは再ダウンロードされない

この数字はたいてい想像より小さい。週に 3 回更新を配信しても、ユーザーがその週にアプリを 1 回しか開かなければ、ダウンロードするのは 3 回分ではなく 1 回分だ。クライアントは最新の更新だけをダウンロードし、残りは飛ばす。速度の面でも帯域幅の面でもこれは良いことだ。ユーザーは余計なものをダウンロードせず、更新はより速く届き、あなたは実際に使われた分だけを支払う。

とはいえ、更新を小さく保つ価値は請求額以外にもある。ダウンロードが速くなり、ユーザーの通信量が減り、全体的な体験が滑らかになる。詳しくは後述する。

特に楽しみにしていることが 1 つある。SDK 55 以降、Hermes バイトコード差分を有効にできる(現在ベータ、ぜひ試してほしい!)。クライアントは完全な JavaScript バンドルをダウンロードする代わりに、インストール済みの内容にバイナリ差分を適用する。これによりダウンロードサイズを大幅に削減でき、ユーザーはより速く更新を受け取り、あなたはより頻繁にリリースできる。私たちはこうした取り組みを通じて、更新の配信コストを下げながらユーザー体験を良くしようとしている。

更新は小さいほど良い理由

更新が小さいほどユーザーのダウンロードは速くなり、1 回あたりの帯域幅消費も減る。EAS Update の使用量にとっても、モバイル回線や限られたデータプランを使うユーザーにとってもだ。バンドルが小さいことはビルドの速さにもつながる。アプリ起動時に更新を読み込むのだから、バンドルがスリムなら起動もきびきびする。そしてバンドルがある程度大きくなると、開発中にもそれを感じるようになる。変更のたびに巨大なバンドルを扱うことになり、live reload が遅くなり始める。以下は知っておく価値のある手法だ。

アセットを最適化する

画像は更新パッケージのサイズをあっという間に押し上げるので、配信前に最適化済みか確認する価値がある。可能な限り画像を圧縮すると効果は明白で、たいていは目で見ても品質の劣化はほとんど分からない。画像が小さければ更新のダウンロードは速くなり、ユーザーのデータ消費も減る。

アセットはアセットのままに

画像が独立したアセットファイルであれば、ダウンロードされるのは 1 回だけ(ビルド経由でも更新経由でも)で、その後は端末に残り続ける。変更がなければ、以降の更新では完全にスキップされる。しかしアセットが JavaScript にインライン化されていると(たとえば base64 エンコードされた画像)、それらはバンドルの一部になり、更新のたびに一緒に運ばれることになる。

頻繁に変わる画像や、バンドルにまったく含めたくない画像には、CDN と expo-image を組み合わせて配信する手がある。デフォルトのキャッシュ戦略が初回読み込み時に画像をディスクへ永続化するので、以降はバンドル済みアセットと同じ振る舞いになり(1 回ダウンロードし、アプリの再起動をまたいで再利用)、しかも更新のサイズは一切増えない。

どのアセットを更新に含めるか選ぶ

プロジェクト内のアセットすべてを更新で配信する必要はない。asset selection を使えば、app config でファイルのマッチパターンを指定し、どのアセットを含めるかを正確に決められる。残りはネイティブビルドに留まり、更新サーバーからダウンロードされることはない。

たとえば、リリースごとに変わるのが app/images ディレクトリ内の画像だけなら、更新の対象をそれらの画像に限定できる:

{
  "expo": {
    "updates": {
      "assetPatternsToBeBundled": [
        "app/images/**/*.png"
      ]
    }
  }
}

マッチングパターンを設定したら、公開前に npx expo-updates assets:verify を実行する。こうしておけば、更新を公開するときに必要なアセットがすべて含まれる——漏れたアセットは利用できず、異常な動作やクラッシュにつながることもある。詳しくはドキュメントを参照。

定期的にアプリストアへ提出する

アプリストアに新しいビルドを提出すると、その時点の最新アセットがすべて含まれる。つまり、それ以降に公開する OTA 更新には、そのビルド以降に変わった部分だけを含めればよくなり、ユーザーのダウンロード量が減る。最近サイズの大きいアセットや数の多いアセットを追加したなら、新しいビルドを出すのは以降の更新をスリムに保つ良い方法だ。

有効なやり方のひとつは、バイナリのリリースを一定のペース(たとえば月1回)で続け、その間の変更は OTA 更新で届けるというもの。ユーザーはより頻繁に改善を受け取れるし、新しいバイナリのたびに以降の更新のアセット基準がリセットされる。

JavaScript bundle のサイズを抑える

OTA アップデートの最適化

JavaScript bundle は、公開するすべての更新に含まれる。Expo Atlas のようなツールを使えば、bundle を視覚的に分解し、どの依存関係がどれだけの容量を占めているかがわかる。結果は意外なことが多い——ユーティリティ関数ひとつのために入れたライブラリが想定よりずっと大きかった、あるいはもう使っていないのに消し忘れていた依存関係が見つかる、といった具合だ。

今すぐローカルの dev server で試せる。Atlas を有効にしてアプリを起動する:

EXPO_ATLAS=true npx expo start

あとは dev server が動いているターミナルで shift + m を押して dev tools のプラグインメニューを開き、Atlas を起動する。

更新を効率よく公開する

ここまでは更新をスリムに保つ話をしてきた。だが公開のしかたも同じくらい重要だ。rollout を使えば、更新がユーザーに届く過程をより細かく制御できるし、更新を内部テストに使えば時間と build credits を節約できる。

rollout で本番更新を公開する

更新を公開すると、デフォルトでは全ユーザーに配信される。ユーザーがダウンロードした更新はすべて帯域消費にカウントされるので、rollout は理にかなった帯域節約策だ。まず小規模に配信して問題がないことを確認し、それから全員に届ける。

更新を内部テストと PR プレビューに使う

開発中、チームに変更を見せて review してもらうには、通常なら build を作り直す必要がある。しかし変更がネイティブコードに触れないなら、OTA 更新で同じことができる——しかも数秒で済む。チームはすでにインストール済みの development build 上で変更をプレビューでき、自動生成される pull request プレビューで確認することもできる。

review とイテレーションを build ではなく更新で回すほど、他の人に変更が届くまでの待ち時間が短くなる。チームは数秒でデバイス上の最新版を手にでき、フィードバックループを早く回し始められる。機能をイテレーションする間、この効果はすぐに積み上がり、build credits も節約できる。しかもこれらの更新をダウンロードするのはチームだけなので、MAU と帯域のコストはほぼゼロ。プランの中で最も費用対効果の高い省力手段のひとつだ。

使用量を追跡する

ここまでに挙げたやり方(更新をスリムにする、段階的に公開する、更新を内部テストに使う)はどれも、EAS Update のプランからより多くの価値を引き出すのに役立つ。とはいえ、進み具合をいつでも確認できるのは良いことだ。

コンソールで使用量を監視する

Expo はアカウントの Billing ページと Usage ページで使用量の概要を提供している。そこでは EAS Update の使用量がまとめて確認できる。現在の請求期間(または指定した期間)に何人の MAU が更新をダウンロードしたか、どれだけ帯域を消費したかがわかる。特に大きなリリースを出した直後に、数字がどうなっているか知りたいときなど、状況を把握するのに便利だ。

料金計算ツールで適切なプランを見つける

どのサブスクリプションプランが自分に合うか迷っているなら、Expo 公式サイトの料金計算ツールが役に立つ。スライダーを動かし、想定 MAU 数、ビルド回数、CI/CD の分数を入力すると、プランを提案してくれる——そのプランに含まれる枠を超えて使った場合は、超過分の概算費用もあわせて計算してくれる。

まずは今の自分に合うプランを選ぶ

プランを選ぶ前に、すべてを見通しておく必要はない。今のニーズを満たすものから始めればいい——アプリが想定より速く成長しても、壁にぶつかることはない。どのプランも使用量に応じて自然に拡張し、必要が変わればいつでも切り替えられる。Expo の価格設定はあなたとともに成長するようにできていて、足を引っ張るものではない。すべてのプランに EAS Update が含まれ、無料プランも例外ではないので、負担なく試し始められる。

まとめ

結局のところ、EAS Update が用意してくれる条件はかなり良い。数秒でユーザーに更新を届け、チームとより速くイテレーションし、自分のペースで拡張できる。更新をスリムにし、段階的に公開し、ここまでに挙げた技を組み合わせれば、ユーザーにはより速い体験を届けつつ、プランに見合った価値を引き出せる。

始める準備はできた?プロジェクトで EAS Update を設定しよう——数分で完了し、設定すればすぐに更新を公開できる。ここまでに触れた話題をさらに深く知りたければ、EAS Update ドキュメントが次の一歩として最適だ。EAS Update の成功事例もぜひ聞かせてほしい!

出典: Expo Blog← ホームへ戻る