Expo SDK 58 ベータ公開:iOS 27、Expo Modules 2.0、Rust 製バンドラー
SDK 58 beta では iOS 27 と Liquid Glass への対応、Expo Modules 2.0、コールドスタート時のバンドルが約2倍速くなる Rust トランスフォーマー、そして一連の破壊的変更が導入される。Expo Go は当面 CLI 経由でしかインストールできない。
日本語
コピー

SDK 58 の beta 期間は今日から3〜4週間。 beta 期間は、開発者が新バージョンを試し、自分のシステムやアプリ構成でリグレッションが入っていないか確認するための期間です。この間も修正と改善を出し続けます。
SDK 58 は iOS 27 向けにビルドされています。今すぐ iOS 27 対応が必要なら、beta 版のままリリースして構いません。SDK 58 beta には React Native 0.88(Release Candidate)が含まれます。0.88 はまだ正式リリースされていないため beta では RC を使っており、0.88 が正式リリースされ次第 stable に切り替え、その後まもなく SDK 58 をリリースします。SDK 58 の完全な release notes は stable まで出ませんが、今回のリリースの規模と破壊的変更は expo/expo リポジトリの各 changelog で今すぐ確認できます。beta が終わったら、すべての changelog をルートの CHANGELOG.md に統合します。
SDK 58 の Expo Go は現時点では Expo CLI 経由でしかインストールできません。対応するのは Android の実機とエミュレータ、iOS シミュレータです。iOS 実機は eas go から(詳細)。App Store と Google Play の Expo Go は stable リリース後まもなく SDK 58 に更新されるので、ストア版が SDK 57 のサポートを切る前にアップグレードする時間はあります。
Discord でoffice hoursも開きます。今回のリリースのテストに協力したい人はぜひ。
SDK 58 は iOS 27 向けにビルド
iOS 27 では UIKit の scene ライフサイクルが必須になり、iPhone アプリはリサイズ可能になります。iOS 27 SDK でビルドしたアプリはこの2つを自動的に得ます。Expo アプリは iOS 27 で正しく起動するために scene ライフサイクルへ移行しました(#46733)。これにより app delegate コールバックの配送方法が変わるので、AppDelegate.swift をカスタマイズしている場合はscene ライフサイクル移行ガイドを読んでください。Expo の各パッケージは UIScreen.main からジオメトリ情報を読まなくなり(#48172、#48315、#48316、#48170、#48169)、expo-modules-core も scene を認識するジオメトリユーティリティを提供します(#48168)。
iOS 27 では requireFullScreen でアプリのリサイズを無効化できなくなり、アプリがリサイズ可能なときは ScreenOrientation.lockAsync がまったく効かない可能性があります。requireFullScreen の config plugin はこれに対応済みです(#48175)。iOS 27 以降での画面向き固定も参照してください。iOS 27 SDK でビルドしたアプリでは、expo-glass-effect が isLiquidGlassAvailable を true として報告します(#49850)。
beta 期間中は、iPhone Duo SDK が開発者に開放された初日から深い統合を実現できるよう、引き続き改善を進めます。
Xcode 27 と SDK 58 ツールチェーンを載せた EAS Build イメージはまもなく提供予定で、使えるようになり次第この記事を更新します。それまでは latest の EAS Build イメージに Xcode 26.6 が入っています。
Xcode 27 の Device Hub 対応
Xcode 27 では Simulator.app が Device Hub に置き換わりました。Expo CLI は Device Hub を認識してシミュレータを起動し、devices:// のディープリンクで対象デバイスにフォーカスします(#46757、#46809)。エディタを離れたくない人には、新しい expo-device-hub 開発ツールプラグインがあります。ブラウザがローカルデバイスのパネルになり、すべての iOS シミュレータと Android エミュレータのライブ画面を直接タップ・スワイプ・入力でき、起動/シャットダウン操作、CPU/メモリ/ネットワークのグラフ、外観・Liquid Glass・文字サイズ・アクセシビリティ設定のトグルも使えます。インストールして(npx expo install expo-device-hub)npx expo start を実行すると、ターミナルにリンクが表示されます。同じ体験を Xcode や Android Studio のないマシンで求めるなら、近日公開のクラウドシミュレータサービス EAS Simulator に注目してください。

App Intents:アプリを Siri と Apple Intelligence に公開する
expo-app-intents を使うと、Expo アプリで Apple の App Intents(Siri、ショートカット、Spotlight、Apple Intelligence)を宣言できます(#47207)。App Intent の型は app-intents ディレクトリ内の Swift inline module に書きます。Apple がビルド時にメタデータを抽出できるのは app target 内のコードだけだからです。このパッケージは呼び出しを JavaScript に配送し、entity の値を保持します。npx expo-app-intents init を実行するとこのディレクトリが作成されます(#47223)。このライブラリはまだ alpha で、ドキュメントとサンプルは追って追加されます。
例:Siri でタスクを完了させる
ある onboarding チェックリストアプリが「タスクを完了する」という intent と、タスクの entity を宣言している。Siri にタスクを完了したいと話しかけると、Siri がアプリ内のタスクを一覧表示してどれか尋ねる。選ぶと intent があなたの JavaScript で実行され、アプリがそれを完了済みにする。アプリを前面に出す必要は一切ない。

Expo UI:iOS のネイティブナビゲーション、新しい Compose コンポーネント、その他いろいろ
すべてのコンポーネントにドキュメントのプレビュー画像が付いた
Expo UI のリファレンスドキュメントでは、各コンポーネントの API の隣にスクリーンショットが表示されるようになった。props を読む前に、何を選ぼうとしているのかが一目で分かる。ドキュメント内の SwiftUI と Jetpack Compose のギャラリーを見てほしい。

iOS ナビゲーション。 @expo/ui に NavigationStack、Toolbar、NavigationLink、NavigationDestination コンポーネント、navigationTitle 修飾子、close ボタンロールが追加された(#49940、#49991)。NavigationSplitView は 2 カラムと 3 カラムのレイアウトに対応した(#50075)。
SwiftUI。 background、tint、border、strokeBorder、containerBackground、presentationBackground、foregroundStyle の各修飾子が任意の ShapeStyle を受け取れるようになり、ビューをマテリアルやグラデーションで着色できる(#48905、#49621、#49767、#49838)。新しく加わったのは Background コンポーネント(#48904)と、scrollClipDisabled(#49780)、geometryGroup(#48838)、listRowSeparatorTint(#48810)、alignmentGuide(#49247)、menuStyle および menuIndicator(#48448)の各修飾子。
Jetpack Compose。 新しく追加されたのは Image(#48521)、DateRangePicker、DateRangePickerDialog(#49788)、VerticalSlider(#49612)コンポーネント。DropdownMenu には cornerRadius と shadowElevation が加わり(#49515、#49896)、RadioButton には enabled と colors が加わった(#49852)。
共通コンポーネント。 BottomSheet に contentPadding、containerColor、contentColor が加わり、ListItem は colors に対応した(#48902、#49575)。Web では BottomSheet がメンテナンスされなくなった vaul を外し、自前の HTML <dialog> に切り替えた(#49509)。
ホストされた React Native ビュー。 <RNHostView> の中に置いたビューが、SwiftUI と Jetpack Compose が配置する位置に基づいて測定されるようになった(#48969、#48970)。これにより、タップが失われる、ジェスチャーを外側のスクロールコンテナに取られる、BottomSheet、Popover、AlertDialog、DropdownMenu の内部がタップできないといった問題が直った。ホストされたテキストフィールドの外側をタップするとキーボードが閉じるようになった(#48788)。SwiftUI の Menu を閉じるタップが、その下にある React Native ビューを押してしまうこともなくなった(#48463、#49775)。
Expo と EAS Observe
EAS Observe は本番環境でアプリのパフォーマンスとエラーを監視するツールで、8 月 20 日から正式に利用できるようになった。SDK 58 では expo-observe に Observe.registerIntegration(#48245)、ObserveErrorBoundary と reportError(#47341、#47871)、errorHandlingEnabled オプション(#48506)、expo-image 連携(#47145)、そして Observe.clientId——各イベントに記録される EAS client ID——が加わった(#49599)。AppMetrics は廃止され、Observe に置き換わった。詳しくは廃止項目を参照。

@expo/agent-cli:agent のために設計された新しい CLI
これまで agent が Expo を学ぶのは我流だった。Expo Go を起動し、Expo Go が対応していない native module を足してランタイムエラーにぶつかり、development build を使うべきだと自力で推測する。どこで Expo CLI を使い、どこで EAS CLI を使うべきかも把握しなければならない。@expo/agent-cli は agent が作り、agent のために設計した新しい実験的 CLI だ。Expo CLI、EAS CLI、expo-doctor の上に載っていて、Expo CLI にフォールバックする。だから agent にこれまでのツールの代わりに使わせればいい。
いくつか便利なコマンドがある。status はアプリを起動せずに Expo Go との互換性を答える。dev はコマンド1つでアプリを動かす。web フレームワークがサーバーとブラウザを同時に立ち上げるのに似ていて、ビルドが必要かどうかは自分で判断し、最速の方法でアプリを起動しようとする。コマンドが次の一手を出力するので、agent はそのまま進められる。smoke は dev にスクリーンショットと停止を足したもので、手元のマシンで開発を始められることを確認するために使う。skills:sync は node_modules にある同じ位置の agent skills を自分のプロジェクトにインストールする。
まず npx @expo/agent-cli@latest agents:setup から始めて、agent には Expo CLI の代わりに @expo/agent-cli を使わせよう。
もっと短い名前がよければ、expo-agent-cli がエイリアスだ。このパッケージ名を譲ってくれた Kazutoyo Tokai に感謝する。この CLI はまだ活発に開発中で、いずれブログで詳しく書く。それまでは試してみて、感想を聞かせてほしい。
ホーム画面ウィジェットが Android に登場
expo-widgets に Android 実装が加わった。ウィジェットは専用の Hermes ランタイムで自分の JS bundle を実行し、インタラクションと Material Colors に対応する(#46961、#47035、#48454)。iOS では Live Activities の LiveActivity.start() と update() に staleDate オプションが増え(#46343)、ActivityKit の識別子が安定し(#48589)、ウィジェット設定が実行時の変更に対応した(#47533)。
Swift Package Manager ビルド
React Native 0.87 に実験的な Swift Package Manager サポートが入り、CocoaPods に代わる選択肢となった。SDK 58 は Expo アプリの下地を整えた形だ。Expo の iOS ソースはリファクタリングされ、Swift、Objective-C、C++ がそれぞれ独立した SwiftPM target としてコンパイルされる(#45906、#49820、#49821、#49832)。React Native npx react-native spm パイプライン向けの Expo autolinking プラグインは review 中で(#49823)、beta 期間中にプレビューとして公開する予定だ。CocoaPods は引き続きデフォルトでサポートされる経路であり、プリコンパイル済みの Expo module もこれまでどおり動作する。
Expo Modules:ビルドが速く、呼び出しが速く、書き方が簡単に
プリコンパイル済み expo-modules-core で Android ビルドを高速化
expo-modules-core は Android 向けにプリコンパイル済みのネイティブライブラリを提供するようになった。これまでクリーンビルドのたび、CI のたび、EAS Build のたびに libexpo-modules-core.so の C++ をソースからコンパイルしており、Expo を使った Android ビルドで最も高くつく工程だった。今は npm パッケージに4つの ABI すべての .so ファイルが含まれ、debug と release の両バリアントをカバーする。空の SDK 58 プロジェクトで計測したところ、4つの ABI の Android debug クリーンビルドは Apple M3 Pro で約80秒、expo-modules-core の C++ コンパイルを飛ばすと約39秒まで縮まり、ほぼ半分になる。コア数の少ないマシン(CI runner など)では削減幅はさらに大きい。省かれるコンパイル量は4つの ABI を合計すると10分を超えるが、12コアのマシンでは多数のファイルを並列に処理することでこれまで隠れていた。
速くなった Expo モジュール
native module の呼び出しは無料ではない。Swift や Kotlin に跨り、値を双方向に変換する固定費がかかり、安価な呼び出しではコストの大半がここに消える。SDK 56 は両プラットフォームでこの部分に手を入れた。iOS ではObjective-C++ レイヤーを取り除き、呼び出しが1.6〜2.3倍速くなった。Android ではリフレクションを Kotlin コンパイラプラグインに置き換え、Record の変換が約6倍速くなり、初回レンダリング時間が約30%短縮した。
SDK 58 は iOS 側でもう一段進めた。単純な値を受け渡し・返却する呼び出しが安くなり(#49761)、長い文字列を双方向に渡すのが最大3.8倍速くなり(#49678)、async 関数が返す promise の生成と resolve のオーバーヘッドも下がった(#49718)。必要な作業は何もない。SDK 58 に上げれば、自分で書いていないものも含めすべての Expo module が速くなる。
Expo Modules 2.0 beta
もう一つの話は、コードを書くときに向き合う API だ。既存の DSL 定義で native module を記述する代わりに、普通の Swift または Kotlin クラスをそのまま書き、JavaScript に公開したいメソッドとプロパティにアノテーションを付けるだけでよくなった。覚えることはこのアノテーション以外に何もなく、コーディング agent にとっても扱いやすい。独自 DSL をまず説明する必要はなく、Swift と Kotlin そのものだから、モデルはもともとよく知っている。
その改良の上に、さらに速い。アノテーションのおかげで、実行時に探すのではなくビルド時に最も直接的な binding を生成できる。同じ SDK で iPhone 16 Pro の Release ビルドを計測したところ、同期呼び出しは DSL より 2.5 倍から 5.6 倍速い。Expo Modules 2.0 抢先看にはベンチマークデータがあり、この API についてもより深く解説している。
Android の Kotlin 側でも同じパターンが見られ、今回は React Native の TurboModules とも比較した。12 項目のマイクロベンチマークで、Expo Modules 2.0 はすべての項目で Expo Modules 1.0 より速く、100 個の数値配列を渡す場合の 1.2 倍から、数値を伴うイベントを送る場合の 39.9 倍まで幅がある。TurboModule との比較でも全項目で上回った。引数なしの呼び出しで 112 ns 対 2,837 ns、20 個のオブジェクト配列を渡す場合で 10.7 µs 対 149.8 µs、オブジェクトを伴うイベント送信で 963 ns 対 8,080 ns だ。

SDK 57 では iOS マクロが実験的にリリースされた。SDK 58 beta では、Expo Modules 2.0 が iOS と Android の両方で beta になる。ドキュメントは beta 期間中に整備される予定で、それまでは抢先看のブログ記事が最良の手引きになる。
fingerprint の新しいデフォルト:不要なネイティブ再ビルドを減らす
バージョン番号を変えたり、node_modules 内のファイルに触れたりしても、fingerprint は変化しなくなった。SDK 58 では fingerprint のデフォルトが balanced プリセットに変わった(#47668)。app.json の version を更新するといったよくあるケースを無視し、native module のハッシュをファイルやディレクトリではなくパッケージ名とバージョンで計算する。追加設定は不要で、ハッシュは安定したままになる。異なるトレードオフが必要な場合はfingerprint プリセットを参照してほしい。
実験的:Rust 製トランスフォーマーでコールドバンドルを約 2 倍高速化
Metro のキャッシュがあればホットバンドルは速いが、コールドバンドルは——プロジェクト全体でも変更されたモジュールでも——ほとんどの時間を Babel が占める。SDK 58 では実験的な代替手段を導入する。それが「Noxcturnal」、oxc をベースにした Rust 製の module transformer で、napi-rs を通じて Node.js に公開される。社内テストでは、単一モジュールの変換時間が約 3 倍、エンドツーエンドのコールドバンドルが約 2 倍速くなった(#48443)。最大のテストアプリでは、約 5,500 ファイルのコールドバンドルが Babel の 5.26 秒から新しいトランスフォーマーの 2.46 秒に短縮され、そのうち 443 ファイルは依然として Babel にフォールバックしている。

app config で experiments.noxcturnalTransformWorker を設定すると試せる。プロジェクトにカスタム transform worker や Babel プラグイン/プリセットがない場合にのみ有効で、Reanimated や Worklets の Babel transform が必要なファイルはスキップされる。まだ非常に初期の取り組みで、実装も数値も安定するまで変わりうる。カスタム Babel transform を使うプロジェクトを含め、より多くのプロジェクトで使えるよう設定項目を追加する予定だ。
Expo Router:データローダーとネイティブタブが安定、ナビゲーションコアを改善
データローダー、サーバーサイドレンダリング、ミドルウェアはすべて安定機能になり、実験的なフラグは不要になった。ネイティブタブ、ツールバー、標準ナビゲーション統合も安定した。
Expo Router のナビゲーションコアも書き直され、ナビゲーション状態が決定的で推論しやすくなり、fork された React Navigation API の大部分を抱えなくなった。ほとんどのアプリは気づかないだろう。ただしカスタム navigator を書いたり、expo-router/react-navigation からインポートしたりしていた場合、一部の API は移行または削除されている。必要なものが見当たらない場合は、何をしたいのかを添えてissue を立ててほしい。
その他の変更は以下に列挙する。ドキュメントへのリンクは順次追加していく。
-
Navigator の移行:JavaScript の
Tabs、TopTabs、DrawerはNativeTabsと同じstandard-navigation統合を使うようになり、挙動がより一貫した。 -
Loader キャッシュ:
loader内でexpo-serverからsetResponseHeaders({ 'Cache-Control': 'private, max-age=60' })を呼ぶと、クライアントがそのレスポンスを 60 秒間キャッシュできる。 -
React transitions と Activity:ナビゲーションは React transitions を使い、次の画面が読み込まれる間も現在の画面を表示し続ける。navigator や screen に
activityEnabledを設定するか、NavigationAwareActivityで画面の一部を包むと、状態を保ち effect をクリーンアップしつつ、非アクティブなコンテンツを隠せる。 -
Web では非同期ルーティングがデフォルトで有効:
expo-router設定プラグインが web 向けにasyncRoutesを自動で有効にする。ルートファイルは個別の JavaScript chunk に分割され、ブラウザがそのルートに遷移したときに読み込まれる。asyncRoutes: { web: false }を設定すればオフにできる。 -
カスタム router API:
extendRouterで組み込み router の一部を上書きしたり、extendRouterActionsでカスタムナビゲーションアクションに handler を追加したりできる。 -
スクリーン単位のエラーバウンダリ:layout に
unstable_settings.screenErrorBoundaryを設定するか、<Stack unstable_screenErrorBoundary={MyErrorBoundary} />を渡せば、エラーを投げたスクリーンにフォールバック UI を表示しつつ、navigator はマウントされたままにできる。 -
オプションの依存関係:Android で
mdprop 付きのNativeTabs.Trigger.Iconを使うにはexpo-symbolsのインストールが必要で、Stack.Toolbarを使うには@expo/uiが必要。どちらもオプションの peer 依存関係になった。
アップグレードの際は移行ガイドを読んでほしい。カスタム navigator を使っている場合や expo-router/react-navigation からインポートしている場合は特に。
プロキシとトンネル経由で dev server に接続する
dev server がプロキシの背後やリモートマシン上で動いていたり、トンネル経由で公開されていたりする場合、development build が安定して接続できるようになったはずだ。これまで development build は起動時に取得する manifest で使用する bundle URL と debugger hostname を受け取っていたが、サーバーがプロキシの背後にある場合や Bonjour で検出された場合、そのアドレスはクライアントから到達できないことがあった。クライアントが対応していれば、manifest は相対 URL を使うようになった(#47255、#48997)。
RCT_METRO_PORT はプリコンパイル済み React Native ではコンパイル時マクロで、8081 に固定されている。そのため expo-dev-client を持たない bare アプリは常に 8081 としか通信せず、そうしたアプリを2つ同時に動かすと互いの reload コマンドに応答してしまう。prebuild はポートを Info.plist の RCTMetroPort キーに書き込み、アプリは起動時にそれを読むようになった(#48098)。Expo CLI のポート選択も一貫性が増し、非対話実行時に即座に失敗するのではなく、次の空きポートにずれるようになった(#47771、#48300)。
より速く、より信頼できる Expo CLI トンネル
Expo CLI に @expo/ws-tunnel 2.0 ベースの新しいトンネル実装が入った(#46696)。接続が速く、安定し、@expo/ngrok も不要になった。試すには:
EXPO_UNSTABLE_TUNNEL_V2=1 expo start --tunnel
使うには Expo アカウントへのログインが必要(expo login)。
EXPO_UNSTABLE_TUNNEL_V2 スイッチは SDK 58 beta の後半で削除され、これがデフォルトのトンネル実装になる。
React Native 0.88(Release Candidate)
SDK 58 beta は React Native を 0.86 から 0.88 release candidate に引き上げ、React Native 0.87 と React Native 0.88 release candidate の変更を同時に取り込んだ。0.88 の要点は:
-
Swift Package Manager ツール:オプションの
npx react-native spmコマンドと SwiftPM パッケージ生成。CocoaPods は引き続きデフォルトでサポートされる経路。 -
Text上のfontVariationSettings:オブジェクト構文で可変フォントの軸を設定でき、同じバージョンでexpo-fontに入った可変フォント対応とうまく噛み合う。 -
TurboModules の
ArrayBuffer:JavaScript のArrayBuffer値が Android と iOS の両方でネイティブ表現を持ち、バイト所有権の取り決めも明示された。 -
React Native DevTools:実験的なパフォーマンススナップショットと、Network パネルでの WebSocket 検査。
詳細は React Native 0.87 release notes と React Native 0.88.0-rc.0 release notes を参照。React Native 0.88 のブログが出たら、ここにリンクを追加する。
PostHog 連携
コマンド1つで Expo アプリに PostHog を組み込めるようになり、捕捉されるすべてのイベントがどの EAS update 由来かを把握できる。eas integrations:posthog:connect を実行すると、EAS CLI が PostHog プロジェクトを作成または連携し、SDK とその設定プラグインをインストールし、環境変数をプロジェクトと EAS に書き込む。PostHog は eas/update_id、eas/build_id、eas/channel、eas/runtime_version といったプロパティを認識し、expo.dev に紐づける。これは EAS CLI の機能なので、どの SDK バージョンでも使える。PostHog 連携 changelog とPostHog の使い方ガイドも読んでほしい。
その他の注目すべき変更
-
expo-camera:CameraView.scanDocumentAsyncを追加。Android と iOS で複数ページのドキュメントスキャンができる(#47362)。 -
expo-file-system:File.digest()を追加。MD5/SHA-1/SHA-256/SHA-384/SHA-512 ハッシュに対応する(#48089)。ネイティブプレビューフロー向けのFile.preview()とFile.canPreview()も追加。 -
expo-audio:プレイリスト付きのロック画面コントロールを追加(#46020)。AudioStream.startFileRecordingAsyncで WAV/PCM ファイルを録音できるようにもなった(#46771)。 -
expo-image:transition.skipOnCacheHitを追加。キャッシュヒット時にトランジションをスキップする(#48181)。さらにsvgVariablesprop を追加。SVG 内でvar()から参照する CSS カスタムプロパティの値を置き換えるもので、同じドキュメントの別々の部分に異なる色を割り当てても画像はベクターのまま保てる(#48663)。値は色に限らない。var()を使う SVG は、この prop を渡さなくてもフォールバック値でレンダリングされるようになった。 -
expo-secure-store:Android にrequireConfirmationを追加。認証が必要な読み書きに使う(#48556)。 -
expo-dev-launcher:disableFab=1とdisableAutoLaunch=1という 2 つの URL パラメータを追加。フローティングボタンを隠し、起動時に dev menu が自動で開くのを防ぐ(#49651)。 -
expo:URLとURLSearchParamsを書き直し、IDNA/TR-46 に対応(#47813)。TextDecoderは速度のために書き直した(#48877)。 -
expo-sqlite:同梱の agent skill でベストプラクティスを agent に共有できる。npx @expo/agent-cli skills:syncを実行すれば自分のプロジェクトにインストールできる(#49867)。 -
expo-font:Android、iOS、web で可変フォントに対応。1 つのフォントファイルで複数のウェイトや字形を含む family を提供できる。useFonts、loadAsync、設定プラグインのいずれからも使える(#48129、#48621、#48432、#49486、#49487、#49485)。詳しくはこちら。 -
expo-notifications:iOS では、通知センターへの呼び出しが別のライブラリが登録したUNUserNotificationCenterDelegateに転送される。これによりexpo-notificationsは他のプッシュライブラリと同じアプリ内で共存できる(#48313)。通知はthreadIdentifierでグループ化できるようにもなった(#49429)。Android では、日付と繰り返しのトリガーにdelivery: 'alarmClock'オプションを追加。AlarmManager.setAlarmClock()を使う——OEM の省電力ポリシーでも遅延しない——ので、時間に敏感なアラームに向く(#49687)。設定プラグインにはlargeIcon属性を追加(#49481)。詳しくはこちら。 -
expo-location:位置プロバイダーの抽象化レイヤーを中心にexpo-locationを書き直している。よりシンプルな位置情報 API、位置の監視、バックグラウンドでの位置更新、iOS の一時的な全精度をリクエストするなどの新しい権限オプションが入る(#49849、#49972、#49988)。この書き直しはオプトインのプレビューとして既存 API と併存するので、この beta にあるexpo-locationのコードは何も変更しなくていい。試せるようになったら改めて詳しく書く。 -
@expo/cli:Android 仮想デバイス(AVD)とadbの管理を書き直し、失敗に対してより堅牢にした(#49258)。
非推奨
-
expo-file-system:File.md5を非推奨。File.digest()を使う(#48089)。 -
expo-modules-core:NativeArrayBufferを非推奨。ArrayBufferを使う(#47106)。 -
expo-observe:AppMetricsのエクスポートを非推奨。Observeを使う(#48901)。 -
expo-sqlite:useLibSQL設定プラグインの属性を非推奨。今後は何の効果もない(#48543)。 -
@expo/ui:iOS ではbackgroundOverlayを非推奨。backgroundを使う(#49621)。borderとstrokeBorderのcolorパラメータを非推奨。contentを使う(#49838)。
注目すべき破壊的変更
-
React Native の strict TypeScript API:React Native 0.87 で strict TypeScript API がデフォルトになった。
react-native/Libraries/*からの deep import は型エラーになり、一部の型の形も変わった。最も目立つのは ref で、ViewInstanceやTextInputInstanceといったインスタンス型を使うようになっている。移行ガイドに沿って進めるか、migrate-to-strict-api skill を使って agent に任せてもいい。移行を先送りしたい場合は tsconfig.json に"customConditions": ["react-native", "react-native-legacy-deep-imports"]を設定する("react-native"は残し、expo/tsconfig.baseは設定済み)。このオプトアウトは React Native 0.88 以降で削除される予定なので、SDK 58 のサイクル中に移行を終わらせる計画でいる。 -
React Native API の削除:
InteractionManager(requestIdleCallbackに移行)、Touchableのルートエクスポート、NativeMethods型、Modalのanimatedprop、そして非推奨だったStatusBarのbackgroundColor、translucent、networkActivityIndicatorVisibleがすべて削除された。ImageBackgroundは非推奨となり、Viewに絶対配置のImageを置く形に変わった。全リストは 0.87 と 0.88.0-rc.0 の release notes を参照。 -
iOS の scene ライフサイクル:iOS 27 SDK が UIScene ライフサイクルを要求するため、
npx expo prebuildは SceneDelegate.swift と Info.plist のUIApplicationSceneManifestエントリを生成するようになり、UIWindowはdidFinishLaunchingWithOptionsではなく scene delegate が生成する(#46733、#46734)。Expo は URL、user activity、Handoff、ライフサイクル、クイックアクションの各イベントをExpoAppDelegateのオーバーライドと購読者に転送するので、これらに依存する config plugin やモジュールはこれまでどおり動作する(#49925、#50032)。ios ディレクトリを手動で管理している場合、bare React Native アプリを使っている場合、あるいは app delegate のメソッドを直接オーバーライドしている場合は、移行ガイドを参照。 -
NODE_ENVと env ファイル:Expo CLI の各コマンドは .env ファイルと app config を読み込む前にNODE_ENVをdevelopmentまたはproductionに設定するようになった。これで動的な app.config.js と .env のカスケードがモード間で常に一致する(#48554、#48741、#48839)。以前はどのコマンドも継承したNODE_ENVをそのまま使い、expo configは設定すらされなかったため、NODE_ENV=test npx expo startは .env.test を読み込んでいた。今後は継承した値は無視され、このコマンドは .env.development を読み込む。テスト内では引き続き Jest がNODE_ENV=testを設定し、@expo/envはそこでも .env.test.local、.env.test、.env を解決する。詳しくは環境変数ガイドを参照。 -
Android アプリテンプレート:release ビルドは gradle.properties の
android.enableMinifyInReleaseBuilds=trueを通じてデフォルトで R8 を有効にする(#50108)。R8 は Java/Kotlin コードを縮小・最適化・難読化し、パッケージサイズを減らして起動時間を改善する。アプリはproguard-android-optimize.txtプリセットで最適化される。リフレクションに依存するライブラリには ProGuard keep ルールが必要になることがある。無効にするにはexpo-build-propertiesでandroid.enableMinifyInReleaseBuildsをfalseに設定する。 -
expo-router:ナビゲーションコアの変更によりナビゲーション状態と route key が決定的になり、ナビゲーションの dispatch は commit 後まで遅延され、fork された react-navigation API のかなりの部分が削除された。@expo/uiとexpo-symbolsはオプションの peer 依存になった。移行ガイドが項目ごとに扱っており、全リストは expo-router changelog にある。 -
expo-file-system:File.write()が非同期になり promise を返すようになった。元の挙動が必要な場合はFile.writeSync()を使う(#45992)。 -
expo-sqlite:libSQL サポートを削除——syncLibSQL()もlibSQLOptionsもなくなった(#48543)。 -
expo-notifications:フォアグラウンド通知は、setNotificationHandlerが別途指示しない限りデフォルトで表示されるようになり、handler が遅くても通知が失われなくなった(#49072)。このリリースにおけるexpo-notificationsのその他の変更はその他の注目すべき変更を参照。 -
@expo/fingerprint:デフォルトプリセットがbalancedになった(#47668)。 -
@expo/ui:iOS では<Host>が中央揃えではなく上揃えになり、flex: 1の host が Android と一致するようになった(#47561)。HStack、VStack、GlassEffectContainerは未設定のspacingをnilとして SwiftUI に転送し、システムデフォルトの間隔を使うようになった。spacing={0}を渡せば元のレイアウトを維持できる(#48441)。Android ではRNHostViewのstyleprop が削除され、modifiersに置き換わった(#48970)。 -
expo-localization:iOS でデバイス言語に基づいてsupportsRTLが RTL を強制しなくなった。レイアウト方向はI18nManagerに従う(#48086)。 -
expo-media-library:iOS のAsset.getUri()とAssetInfo.uriが Photos 内の動画の現在のバージョンを解決するようになった。従来の動作にするにはversion: AssetUriVersion.ORIGINALを渡す(#48640)。 -
@expo/cli:expo loginはデフォルトでブラウザログインを使うようになった。従来の動作にするには--no-browserか--username/--passwordを使う(#46832)。
ツールのバージョン要件
-
Node.js:Expo ツールチェーンは Node.js 22 系なら 22.13 以上、24 系なら 24.3 以上、または Node.js 26 以上を要求するようになった。23 や 25 のような奇数バージョンはサポートされない(#47202)。
-
Android Gradle Plugin:Expo modules ツールチェーンが AGP 9 に対応した(#46766、#46769)。
既知のリグレッション
- 現時点で報告はない。beta 期間中に新たな報告があればこのセクションを更新する。
この beta 版を試すには
SDK 58 beta で新規プロジェクトを作成
# npm
npx create-expo-app@latest --template default@next
# bun
bun create expo-app --template default@next
# pnpm
pnpm create expo-app --template default@next
# yarn
yarn create expo-app --template default@next
注意:create-expo-app は使用中のパッケージマネージャーで依存関係をインストールする。例えば npx なら npm、yarn create なら yarn。
既存プロジェクトのアップグレード
Claude Code と組み合わせて、私たちの expo-upgrade skill でアプリを beta にアップグレードできる。問題があればぜひフィードバックしてほしい。今後数週間でさらに改善していく。
以下は手動でのアップグレード手順。
- すべての依存関係を SDK 58 に合わせてアップグレード:
npx expo install expo@next --fix
- SDK 58 のドキュメントを読む。完全な API リファレンスがある。
テストしてほしいこと
-
アップグレードとテスト:
npx expo install expo@next --fixを実行し、ネイティブプロジェクトアップグレードアシスタントと照らし合わせ、問題があれば報告する。 -
ネイティブビルド:EAS Build でビルドする(Xcode 27 と SDK 58 を載せたイメージはまもなく公開、上記参照)。ローカルに Xcode と Android Studio があるなら、prebuild して実行してみるのもよい:
npx expo prebuild --clean、npm run ios、npm run android。あるいはnpx expo runを試す。新しい問題を見つけたら報告してほしい。 -
ドキュメントの不足を見つけた?教えてほしい。
問題の報告方法
-
可能なら根本原因を特定する:これは常に非常に役立ち、修正が早くなる。
-
SDK 58 beta を使っていると明記する:それに応じて優先度を調整する。
beta をテストしてくれてありがとう、本当に感謝している!