Convex:1つのコマンドで Expo アプリにバックエンドを接続する
Expo と Convex は、「アプリはあるのにバックエンドがない」という段階をコマンド1つに圧縮した。プロジェクトの自動作成、環境変数の書き込み、型の生成までこなし、あとは useQuery がデータに追随して自動で更新される。
日本語
コピー

本記事は、Convex 開発者コミュニティ責任者 Wayne Sutton によるゲスト投稿です。EAS CLI のコマンド1つで、Expo アプリにリアクティブで型完備の Convex バックエンドを設定・接続できます。個別のサインアップも、管理画面をいくつも開く必要も、トークンをコピペして回る作業も要りません。
開発者と話していると、決まって訪れる瞬間がある。アプリはもう作り終えていて、画面は動くし、ナビゲーションも快適で、デモもうまく決まる。そこへ誰かが「データはどこに保存してるの」と聞いてきて、ああバックエンドがまだだった、と気づく。それからデータベースを選び、どこかでアカウントを作り、プロジェクトを立ち上げ、ダッシュボードからデプロイ URL をコピーして環境設定に貼り、ビルド設定用に同じ変数をもう一度セットし、次にこのプロジェクトを動かす人がつまずく前に、全部ちゃんと埋まっていることを祈る。
Expo の人たちが言っていたのは、「アプリがある」状態と「バックエンド付きのアプリがある」状態の間のこの道のりが、何年もの間 Expo 体験における最大の穴だったということだ。だから僕らは彼らと一緒にそれを埋めた。今ならコマンド1つで、Convex(僕が所属するリアクティブデータベース兼バックエンドプラットフォーム)を Expo アプリに接続できる:
eas integrations:convex:connect
このコマンドがプロビジョニングと配線を全部やってくれる。オンボーディングの中で Convex に個別サインアップすることも、OAuth リダイレクトを踏むことも、2つのダッシュボードを行き来することもない。手に入るのは型完備のリアクティブなバックエンドと、ローカル開発とビルドの両方に設定済みの環境変数だ。ここが一番気に入っている点で、プロジェクトにサードパーティのサービスを無理やり差し込んだという感触ではなく、最初からそこにあった機能のように感じられる。
Convex で何ができるか
Convex は、リアルタイムデータベース、サーバー関数、ファイルストレージ、検索、スケジューリング、型安全なクライアントライブラリを備えたバックエンドプラットフォームだ。バックエンド関数は TypeScript で書き、クライアントがそれを購読する。裏側のデータが変われば useQuery の結果はひとりでに更新される。手動での再取得も、キャッシュ無効化のコードも、手書きの REST エンドポイントも要らない。
型はバックエンドのコードから生成されるので、コンポーネントで呼ぶクエリと convex/ ディレクトリに書いた関数は常に同期している。サーバー側でフィールド名を変えれば、クライアントのどこが壊れるかを TypeScript が教えてくれる。ミートアップで多くの開発者が初めてこれにぶつかる瞬間を見てきたが、たいていそこで身を乗り出して真剣に聞き始める。
どんなときに使うか
Expo アプリが「ユーザーが見ている間に変化する」データを読み書きする必要があるなら、これを使うべきだ。チャット、プレゼンス、ライブスコア、共同編集のチェックリスト——データが変わったら画面も即座に更新されるべき場面すべて。Convex の購読モデルはこの形によく合っていて、自分で WebSocket を立てたりポーリングを書いたりする必要はない。
プロジェクトの初期段階でも、これが一番速い道だ。僕が一番気にかけているのはこの層で、アイデアと Expo プロジェクトがあって、1週間後ではなく今日、本物のバックエンドが欲しいという人たち。コマンド1つでそこに辿り着けて、あとから必要に応じて関数やスケジューリング、ファイルストレージへと育てていける。
アプリが既存の社内 API を包む薄いクライアントにすぎない場合や、データが完全に静的な場合は、おそらく要らない。リアルタイムデータが本当に必要なときに手を伸ばせばいい。
Convex を Expo アプリに接続する方法
必要なのは Expo アカウント、インストール済みの EAS CLI(npm install -g eas-cli)、そして eas init で EAS に紐付け済みの Expo プロジェクトだ。
プロジェクトのディレクトリで実行する:
eas integrations:convex:connect
コマンドはデプロイのリージョン、プロジェクト名、必要ならチーム名を尋ねてくる。チーム名を聞かれるのは、新しい Convex チーム接続を作る必要があるときだけだ。引数をまとめて一度に渡すこともできる:
eas integrations:convex:connect --region aws-us-east-1 --team-name "your-team" --project-name "your-app"
このコマンドは裏でこういうことをしている:
npx expo install convexでconvexパッケージをインストールする- EAS アカウント用の Convex チーム接続を作るか、既存のものを再利用する
- この Expo アプリ用の Convex プロジェクトとデプロイを作成する
CONVEX_DEPLOY_KEYとEXPO_PUBLIC_CONVEX_URLを.env.localに書き込むEXPO_PUBLIC_CONVEX_URLを EAS 環境変数として production、preview、development の3環境すべてに設定する- 確認済みメールアドレスに招待を送り、あとからこの Convex チームを引き取ってダッシュボードを開けるようにする
最後の点は単独で触れておく価値がある。招待は非同期なので、それを待って足を止めることなく作業を続けられる。すぐに Convex の開発サーバーを立ち上げよう:
npx convex dev
これが(まだなければ)ローカルの convex/ ディレクトリを作り、型付きの API ファイルを生成し、実行中は関数とデプロイを同期させ続ける。
あとはアプリを provider で包む。Expo Router のプロジェクトなら app/_layout.tsx を編集する:
import { ConvexProvider, ConvexReactClient } from 'convex/react';
import { Stack } from 'expo-router';
const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!, {
unsavedChangesWarning: false,
});
export default function RootLayout() {
return (
<ConvexProvider client={convex}>
<Stack />
</ConvexProvider>
);
}
convex/ ディレクトリにクエリ関数を追加する:
import { query } from './_generated/server';
export const get = query({
args: {},
handler: async ctx => {
return await ctx.db.query('tasks').collect();
},
});
そして画面から呼び出す:
import { api } from '@/convex/_generated/api';
import { useQuery } from 'convex/react';
import { Text, View } from 'react-native';
export default function Index() {
const tasks = useQuery(api.tasks.get);
return (
<View>
{tasks?.map(task => (
<Text key={task._id}>{task.text}</Text>
))}
</View>
);
}
Convex のダッシュボードでデータを1行書き換えれば、デバイス上のリストが更新される。ループはこれで一周だ。
agent に設定させる
僕が付き合いのある開発者の多くは今、AI agent でコードを書いているので、そのやり方でも試してみた。コマンド1つで引数もはっきりしているから、コーディング agent への指示としてよく合う。以下を貼り付ければいい:
僕の Expo プロジェクトで
eas integrations:convex:connectを実行して、Convex バックエンドをプロビジョニングして接続して。それからapp/_layout.tsxにConvexProviderをprocess.env.EXPO_PUBLIC_CONVEX_URLで追加して、convex/ディレクトリにサンプルのtasksクエリを書いて、ホーム画面でuseQueryとしてレンダリングして。
agent に必要なものは揃っている。設定すべきダッシュボードも、読み上げて渡すべきキーもない。
この連携の管理
この紐付けは、あとから数個のコマンドで確認・変更できる:
eas integrations:convex:project
eas integrations:convex:dashboard
eas integrations:convex:team
eas integrations:convex:team:invite
eas integrations:convex:project:delete や eas integrations:convex:team:delete で解除した場合、EAS が消すのは自分側の連携メタデータだけで、Convex 上のものには一切触れない。データもデプロイもそのまま残る。
知っておくべきこと
このコマンドはメールでの招待を送るもので、フローの中でそのまま Convex にログインさせるわけではない。だからフルアクセスのダッシュボードは、あなたが承諾して初めて使えるようになる。リージョンは初回リリース時点で aws-us-east-1 と aws-eu-west-1 から選べる。あと EXPO_PUBLIC_CONVEX_URL は設計上公開変数だ。クライアントがあなたのデプロイにアクセスするために必要だからで、本当のシークレットは Convex の環境変数かサーバー側関数に置くこと。アプリバンドルには入れない。
どこから始めるか
- コマンド1つでバックエンドの開設と接続まで完了し、環境変数はローカル開発とビルド用にすでに用意されている。
- 手に入るのはレスポンシブで型の揃ったデータベース。データが変われば
useQueryが自分で更新する。 - 解除は安全。消えるのは EAS のメタデータであって、あなたの Convex リソースではない。
すでに Expo プロジェクトがあるなら、eas init してから eas integrations:convex:connect すれば、コーヒーが冷める前にバックエンドが手に入る。詳しいチュートリアルはConvex の使い方ガイド、Convex の概要ではドキュメント、関数、サブスクリプションがどう噛み合うかを説明している。
何か作ったら教えてほしい。Convex Discord によくいて、Expo Discord も見ている。どこで時間が浮いたか、どこで詰まったか、ぜひ知りたい。