Counts the Clouds

Neon Postgres Preview IntegrationをVercelにインストールする
2025.03.01

Neon
Vercel

josewa-leonard-james-cp3M_x-0Uzc-unsplash.jpg

NeonはサーバーレスPostgresのDBaaSで、データベースのブランチを作成する機能があり、Vercelへの統合が簡単にできる。

VercelのPreview機能は、フィーチャーブランチの環境を自動的に作成してくれるので便利だが、同様にフィーチャーブランチのデータベースを自動的に作成できると便利なのではないかと思い、試してみた。

アプリケーションの準備

MPAのアプリケーションを作りたいので、簡単のためT3 Stackを使用する。詳細は割愛する。Next.jsとPrismaの組み合わせでもいいと思う。

認証はセットアップの説明を省くためなしにした。Neonを使うためデータベースはPostgresにしておく。

% npm create t3-app@latest


> npx
> create-t3-app

   ___ ___ ___   __ _____ ___   _____ ____    __   ___ ___
  / __| _ \ __| /  \_   _| __| |_   _|__ /   /  \ | _ \ _ \
 | (__|   / _| / /\ \| | | _|    | |  |_ \  / /\ \|  _/  _/
  \___|_|_\___|_/‾‾\_\_| |___|   |_| |___/ /_/‾‾\_\_| |_|


│
◇  What will your project be called?
│  create-t3-app
│
◇  Will you be using TypeScript or JavaScript?
│  TypeScript
│
◇  Will you be using Tailwind CSS for styling?
│  Yes
│
◇  Would you like to use tRPC?
│  Yes
│
◇  What authentication provider would you like to use?
│  None
│
◇  What database ORM would you like to use?
│  Prisma
│
◇  Would you like to use Next.js App Router?
│  Yes
│
◇  What database provider would you like to use?
│  PostgreSQL
│
◇  Should we initialize a Git repository and stage the changes?
│  Yes
│
◇  Should we run 'npm install' for you?
│  Yes
│
◇  What import alias would you like to use?
│  ~/
# ...

データベースを起動する。

% ./start-database.sh

スキーマをデータベースに反映する。

% npm run db:push
# prisma db push

アプリを起動する。T3 Stackのデフォルト状態で起動する。

% npm run dev

フォームから送信できて、データベースに保存されるようにしておく。

Vercelプロジェクトの連携

マイグレーションファイルを生成する。

% npm run db:generate
# prisma migrate dev

Vercel上でPrismaを使用するためのビルドコマンドを追加しておく。

{
  "scripts": {
    "vercel-build": "prisma generate && prisma migrate deploy && next build"
  }
}

GitHubにリポジトリを作成し、これまでの変更をプッシュしておく。

% gh repo create create-t3-app --private --source=.

Neonとの接続のためVercelプロジェクトだけ先に作成する。まだデータベースがないのでデプロイは失敗してしまうが、あとでセットアップしなおすのでいったん置いておく。

先ほど作成したビルド用のコマンド(npm run vercel-build)をBuild Commandに設定しておく。

NeonとVercelの接続

VercelのプロジェクトができたらNeonを接続していくが、ここでVercelのStorageからNeonを接続するとPreview Integrationが使えないという罠がある(2025年2月現在)。Preview Integrationを使いたいなら逆にNeonのコンソールからVercelに接続しなければならない。

まず、Neonのプロジェクトを作成する。現時点で一番近い、AWSのシンガポールリージョンを選択する。東京リージョンはないので興味がある方はリクエストしておくといいかもしれない。

NeonのプロジェクトができたらIntegrationsからVercelのIntegrationを追加していく。

Install from Vercel Marketplaceをクリックする。

VercelのMarketplace画面に移動するのでInstallをクリックする。先ほど作成したNeonプロジェクトを使いたいので、Link Existing Neon Accountを選択してContinueをクリックする。

以降ダイアログに従って進める。

接続に成功すると、Neonのコンソールにvercel-devというブランチが追加されている。このブランチはVercelのDevelopment環境(ローカル用)で、Preview環境のブランチはまだない。

Vercelの環境変数にNeonのデータベース情報が追加されていることを確認する。

Production用のデータベースが設定できているので、mainブランチを再ビルドしておく。先ほど見たT3 Stackのデフォルトアプリがデプロイされるはず。

Preview Integrationを使ってみる

新しいブランチをチェックアウトする。

% git switch -c feature/modify-schema

Prismaのスキーマファイルを、nameに名前を、textに内容を入力するように変えてみる。スキーマが変更されるなら何でもよい。

  model Post {
      id        Int      @id @default(autoincrement())
      name      String
+     text      String
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt

      @@index([name])
  }

マイグレーションを実行する。

% npm run db:generate
# prisma migrate dev

tRPCのRouterをスキーマに合わせて修正する。

  create: publicProcedure
-   .input(z.object({ name: z.string().min(1) }))
+   .input(z.object({ name: z.string().min(1), text: z.string().min(1) }))
    .mutation(async ({ ctx, input }) => {
      return ctx.db.post.create({
        data: {
          name: input.name,
+         text: input.text,
        },
      });
    }),

UIを修正して、新しいブランチにコミットし、プッシュする。

// ...
  export function LatestPost() {
    const [latestPost] = api.post.getLatest.useSuspenseQuery();

    const utils = api.useUtils();
    const [name, setName] = useState("");
+   const [text, setText] = useState("");
    const createPost = api.post.create.useMutation({
      onSuccess: async () => {
        await utils.post.invalidate();
        setName("");
+       setText("");
      },
    });
// ...
      <form
        onSubmit={(e) => {
          e.preventDefault();
-          createPost.mutate({ name });
+          createPost.mutate({ name, text });
        }}
        className="flex flex-col gap-2"
      >
// ...
+        <input
+          type="text"
+          placeholder="Text"
+          value={text}
+          onChange={(e) => setText(e.target.value)}
+          className="w-full rounded-full px-4 py-2 text-black"
+        />
// ...

デプロイされた変更後のアプリはこのようになっている。

VercelにPreview環境のデータベース情報が追加されている。

Neonにもブランチが追加されている。

Previewブランチにスキーマの変更が反映され、データが送信されている。

なお、Neonではデータベースブランチのマージはなく、単純にそれぞれの環境で最新のスキーマが反映される。

Freeだと、プロジェクトが10件まで、1プロジェクトにつき10件のブランチを作成できる。学習用途やプロトタイプ用途であれば問題なく使えるのではないだろうか。東京リージョンがないのもあり、課金して本番用途で使うのはまだ難しいかもしれない。