Next.jsアプリケーションのVercel + Supabase + Prisma構成における本番環境と開発環境での環境構築ガイド

Next.jsアプリケーションのVercel + Supabase + Prisma構成における本番環境と開発環境での環境構築ガイド

Clock Icon2025.02.26

はじめに

普段の個人開発ではNext.jsを用いてアプリケーションを作成することが多く、以下の構成を頻繁に使用しています。
フロントエンド/バックエンド:Next.js
ホスティング:Vercel
データベース:Supabase (PostgreSQL)
ORM:Prisma

毎回この構成で環境構築する際に都度調べながら実装しているので、そろそろしっかりと体系的にブログにしておこうと思います。
今回作成するアーキテクチャの構成図は以下のようなものです。

スクリーンショット 2025-02-24 15.03.38

本番環境ではVercelサーバーにアプリケーションをデプロイし、本番環境のSupabaseに接続します。
開発環境(ローカル環境)では、コンテナ上でローカルのSupabase DBを立ち上げてそちらに接続するようにします。
こうすることで互いの環境が干渉することなくアプリケーション開発に集中することが可能です。

以下の手順で環境構築を行なっていきたいと思います。

  1. Next.jsプロジェクト作成
  2. 本番環境Supabase作成
  3. Prismaセットアップ
  4. 開発環境(ローカル)Supabase作成
  5. Vercelサーバーへのデプロイ

使用PCはMacです。

1. Next.jsプロジェクト作成

まずは開発環境(ローカル)でNext.jsプロジェクトを作成します。
スクリーンショット 2025-02-26 22.08.08

create-next-appコマンドを使用して、Next.jsの雛形を作成します。

https://nextjs.org/docs/app/getting-started/installation#automatic-installation

zsh
npx create-next-app@latest

プロンプトに回答して、Next.jsプロジェクトを起動してください。自分は今回「test-next-app」という名前でプロジェクトを作成しました。
完了したら、プロジェクト配下に移動して開発環境を起動してみます。

zsh
cd test-next-app
npm run dev  

> test-next-app@0.1.0 dev
> next dev --turbopack

   ▲ Next.js 15.1.7 (Turbopack)
   - Local:        http://localhost:3000
   - Network:      http://192.168.10.102:3000

 ✓ Starting...
 ✓ Ready in 703ms

http://localhost:3000にアクセスし、ローカルサーバーが立ち上がっていることが確認できれば完了です。
スクリーンショット 2025-02-24 16.01.18

2. 本番環境Supabase作成

次に、Supabaseにて本プロジェクトの本番環境DBを作成していきます。
スクリーンショット 2025-02-26 22.11.46
以下リンクにアクセスし、 「Start your project」 を選択してください。サインアップが完了していない場合は先にサインアップをしてください。
https://supabase.com/

Organization(組織)がまだない場合は、先に作成します。
プロジェクトを作成する際、画像の赤線で囲ってある Database Passwordを設定し、必ず控えておいてください。 のちの設定で使用します。
また、Regionは「Northeast Asia (Tokyo)」にしておきます。
スクリーンショット 2025-02-24 16.13.02
「Create new project」 を押してプロジェクト作成を完了します。
これにてDBの用意は完了です。とても簡単ですね。
この時点ではまだTable Editorを見てもなにもテーブルがないことが確認できます。

スクリーンショット 2025-02-24 16.20.51

3. Prismaセットアップ

スクリーンショット 2025-02-26 22.16.00

公式ドキュメントに従いPrismaのセットアップを行います。
https://www.prisma.io/docs/getting-started/quickstart-sqlite

Prismaインストール

Prisma CLIをインストールします

zsh
npm install prisma --save-dev

Prismaセットアップ

initコマンドを実行してprisma/schema.prismaを自動生成します。今回はデフォルトのpostgreSQLを使用するので、特にオプションは指定しません。

zsh
npx prisma init
実行結果
zsh [~/test-next-app]
npx prisma init

✔ Your Prisma schema was created at prisma/schema.prisma
  You can now open it in your favorite editor.

warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.

Next steps:
1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver, mongodb or cockroachdb.
3. Run prisma db pull to turn your database schema into a Prisma schema.
4. Run prisma generate to generate the Prisma Client. You can then start querying your database.
5. Tip: Explore how you can extend the ORM with scalable connection pooling, global caching, and real-time database events. Read: https://pris.ly/cli/beyond-orm

More information in our documentation:
https://pris.ly/d/getting-started

以下のようなファイルがprisma/schema.prismaに生成されます。

prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

DBモデル定義

https://www.prisma.io/docs/getting-started/quickstart-sqlite#2-model-your-data-in-the-prisma-schema
DBテーブルの定義をこのschemaファイルには記述します。公式ドキュメントの例と全く同じものを貼り付ってみます。

prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

+model User {
+ id    Int     @id @default(autoincrement())
+ email String  @unique
+ name  String?
+ posts Post[]
+}

+model Post {
+ id        Int     @id @default(autoincrement())
+ title     String
+ content   String?
+ published Boolean @default(false)
+ author    User    @relation(fields: [authorId], references: [id])
+ authorId  Int
+}

マイグレーション

https://www.prisma.io/docs/getting-started/quickstart-sqlite#3-run-a-migration-to-create-your-database-tables-with-prisma-migrate

次に、実際に上で作成したスキーマファイルを実行してテーブルを作成してみましょう。
ただ現時点では開発環境のDBを用意していないので、一旦本番環境で正しくテーブルが作成できるかを確認してみます。(後ほど開発環境を用意します)

スクリーンショット 2025-02-26 22.18.51

先ほど作成したSupabaseプロジェクトを開きます。Connect タブから ORMPrisma を選択します。
中身をそのまま.evnにコピーして貼り付けます。
スクリーンショット 2025-02-26 15.22.20

スクリーンショット 2025-02-26 15.24.50

プロジェクト配下の.envファイルにこの値を貼り付けます。その際に、[YOUR-PASSWORD]となっているところを先ほど控えておいたご自身のDBパスワードに置き換えてください。

.env
# Connect to Supabase via connection pooling with Supavisor.
DATABASE_URL="postgresql://postgres.xxxxxxxxxxxxxxxxxxxx:examplepassword@aws-0-ap-northeast-1.pooler.supabase.com:6543/postgres?pgbouncer=true"

# Direct connection to the database. Used for migrations.
DIRECT_URL="postgresql://postgres.xxxxxxxxxxxxxxxxxxxx:examplepassword@aws-0-ap-northeast-1.pooler.supabase.com:5432/postgres"

また、prisma/schema.prismaもSupabase用に置き換えます。具体的には、directUrlを追加するだけです。
スクリーンショット 2025-02-26 16.50.24

prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

このように設定することで、.envで指定したSupabaseへのURLに対してPrismaがマイグレーションやSQLを実行してくれるようになります。

それでは実際に本番環境のDBに対してマイグレーションが実行できるかを試してみたいと思います。
以下のコマンドを実行してください。

zsh
npx prisma migrate dev --name init
実行結果
zsh
npx prisma migrate dev --name init                                                                               

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "postgres", schema "public" at "aws-0-ap-northeast-1.pooler.supabase.com:5432"

Applying migration `20250226075956_init`

The following migration(s) have been created and applied from new schema changes:

migrations/
  └─ 20250226075956_init/
    └─ migration.sql

Your database is now in sync with your schema.

Running generate... (Use --skip-generate to skip the generators)

✔ Generated Prisma Client (v6.4.1) to ./node_modules/@prisma/client in 50ms

prisma/migrationsディレクトリが作成され、SQLが生成されていることが確認できると思います。

スクリーンショット 2025-02-26 17.31.30

また、SupabaseのTable Editorを見ると本番環境にprisma/schema.prismaで定義したDBテーブルモデルが反映されていることもわかります。
スクリーンショット 2025-02-26 17.03.06
また、自動で@prisma/clientがインストールされ、テーブルモデルの型を定義してくれるprisma generateコマンドも同時に実行されます。

これにより、DBのマイグレーションが成功し、DB操作を型安全に実装できるようになりました。

接続確認

では、マイグレーションが完了したので実際にNext.jsからUserが作成できるかの接続確認をしてみたいと思います。

以下のコードを、app/page.tsxにそのまま貼り付けてください。

app/page.tsx
import Form from "next/form";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export default function Home() {
  // Server Action
  async function createUser(formData: FormData) {
    "use server";

    const name = formData.get("name");
    const email = formData.get("email");

    try {
      // ユーザー作成処理
      await prisma.user.create({
        data: {
          name: name as string,
          email: email as string,
        },
      });

      console.log("ユーザー作成に成功しました");
    } catch (error) {
      console.error("ユーザー作成に失敗しました, " + error);
    }
  }

  return (
    <div className="max-w-md mx-auto mt-10 p-6 bg-white rounded-lg shadow-md">
      <Form action={createUser} className="space-y-4">
        <div>
          <label
            htmlFor="name"
            className="block text-sm font-medium text-gray-700"
          >
            名前
          </label>
          <input
            type="text"
            name="name"
            id="name"
            className="text-black mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
          />
        </div>
        <div>
          <label
            htmlFor="email"
            className="block text-sm font-medium text-gray-700"
          >
            メールアドレス
          </label>
          <input
            type="email"
            name="email"
            id="email"
            className="text-black mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
          />
        </div>
        <button
          type="submit"
          className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
        >
          ユーザーを作成
        </button>
      </Form>
    </div>
  );
}

この状態でローカルサーバーを起動してみます。npm run dev

スクリーンショット 2025-02-26 17.34.55

これは、名前とメールアドレスを入力するフォームを用意して、Userテーブルにレコード作成のPOSTリクエストを送る処理を実装しています。実際に名前とメールアドレスを入力して送信し、本番環境のUserテーブルにレコードが追加されていることが確認できたら成功です。

スクリーンショット 2025-02-26 17.37.23

これにて、ローカルの開発環境から本番環境のSupabaseへの連携の設定が完了しました。
次は開発環境のSupabaseを用意してそちらに接続できるようにしていきたいと思います。

4. 開発環境のSupabase作成

開発環境のSupabase DBサーバーをコンテナで起動する

スクリーンショット 2025-02-26 22.24.24
公式が用意してくれているSupabase CLIを用いて簡単に開発環境のDBをコンテナ上に用意することができます。
https://supabase.com/docs/guides/local-development

コンテナを使用するため、Docker Desktopを事前にインストールしておく必要があります。用意できていない方はDockerのインストールをしてください。自分は代替サービスとしてRancher Desktopを使用していますが、特に操作に変わりはありません。
https://www.docker.com/products/docker-desktop/

準備ができたら、公式ドキュメントに従いSupabaseの開発環境を構築していきます。
自分はMacを使用しているのでbrewでインストールします。

zsh
brew install supabase/tap/supabase

インストールが完了したら、supabase initコマンドを使用してセットアップを行います。

zsh
supabase init                                                                                     

Generate VS Code settings for Deno? [y/N] N
Generate IntelliJ Settings for Deno? [y/N] N
Finished supabase init.

エディタの設定は行わないため、プロンプトには「N」 を入力しましたが、自身の環境に合わせて変更してください。
完了すると、supabaseディレクトリが作成され、諸々設定ファイルなどが追加されます。
最後に、supabase startコマンドを使用してコンテナを起動します。少々時間がかかるかと思います。

zsh
supabase start

起動が完了すると以下のようなログが表示されます。

zsh
Started supabase local development setup.

         API URL: http://127.0.0.1:54321
     GraphQL URL: http://127.0.0.1:54321/graphql/v1
  S3 Storage URL: http://127.0.0.1:54321/storage/v1/s3
          DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
      Studio URL: http://127.0.0.1:54323
    Inbucket URL: http://127.0.0.1:54324
      JWT secret: super-secret-jwt-token-with-at-least-32-characters-long
        anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
service_role key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU
   S3 Access Key: 625729a08b95bf1b7ff351a663f3a23c
   S3 Secret Key: 850181e4652dd023b7a98c58ae0d2d34bd487ee0cc3254aed6eda37307425907
       S3 Region: local

この中から、以下のURLにアクセスしてください。
Studio URL: http://127.0.0.1:54323

すると、ローカル環境でSupabaseが立ち上がっていることが確認できると思います。
スクリーンショット 2025-02-26 18.27.06

コンテナを停止したい場合は、supabase stopコマンドを実行してください。

開発環境のSupabaseに接続する

スクリーンショット 2025-02-26 22.25.49

現状だとまだ開発環境のDBにテーブルなどは特に作成されていないので、これから先ほどのprisma/schema.prismaファイルで定義したDBモデルを反映させていきたいと思います。

そのためには、先ほど本番環境に接続する際に設定した.envファイルを修正し、DATABASE_URLDIRECT_URLをローカルのものと置き換えます。先ほどのログの中から、 DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgresを確認してこちらに置き換えます。

.env
# Connect to Supabase via connection pooling with Supavisor.
- DATABASE_URL="postgresql://postgres.xxxxxxxxxxxxxxxxxxxx:examplepassword@aws-0-ap-northeast-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
+ DATABASE_URL="postgresql://postgres:postgres@127.0.0.1:54322/postgres"

# Direct connection to the database. Used for migrations.
- DIRECT_URL="postgresql://postgres.xxxxxxxxxxxxxxxxxxxx:examplepassword@aws-0-ap-northeast-1.pooler.supabase.com:5432/postgres"
+ DIRECT_URL="postgresql://postgres:postgres@127.0.0.1:54322/postgres"

これにより、DBの接続先が本番環境から開発環境(ローカル)に変更されます。
この状態で、マイグレーションコマンドを実行します。

zsh
npx prisma migrate dev 

これにより開発環境のSupabase上に同じようにテーブルが作成されます。
さらにこの状態で、先ほどのUserフォームから名前とメールアドレスを送信すると、開発環境のSupabaseにUserレコードが作成されることが確認できたら開発環境の作成の成功です。

スクリーンショット 2025-02-26 18.39.13

5. Vercelサーバーへのデプロイ

最後に、VercelへNext.jsアプリケーションをデプロイし、本番環境のアプリケーションからは本番環境へのSupabaseへ接続できるようにしたいと思います。

スクリーンショット 2025-02-26 22.28.25

buildコマンドの修正

Vercelにデプロイする前に、buildコマンドを修正する必要があります。
Vercelでのビルド中にPrisma Clientの自動生成をトリガーさせるために、buildコマンドにprisma generateも実行されるように追加してあげます。また、DBスキーマに変更があった際にそれを本番環境にも反映させる必要があるため、prisma migrate deployコマンドも追加してあげます。

https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-vercel#cicd-workflows

package.json
"scripts": {
    "dev": "next dev --turbopack",
-   "build": "next build",
+   "build": "prisma generate && next build",
    "start": "next start",
    "lint": "next lint"
  }

Vercelデプロイ

リポジトリをVercelサーバーへデプロイします。
サインアップがまだの場合は、先にサインアップを完了させてください。
https://vercel.com/

サインアップが完了したら、Vercelにサインインしてプロジェクトを作成します。
どのGithubリポジトリをimportしてデプロイするかを問われるので、作成したアプリを選択します。
スクリーンショット 2025-02-26 18.48.00

また、その際設定で環境変数を設定できるので、本番環境のDBへのDATABASE_URLDIRECT_URLを設定しておきます。
スクリーンショット 2025-02-26 18.51.58

`DATABASE_URL`と`DIRECT_URL`の取得方法

先ほど解説したように、これら本番環境のDBへのDATABASE_URLDIRECT_URLはSupabaseのConnectタブから確認できます。[YOUR-PASSWORD]のところを本番環境のPasswordに置き換え変えることを忘れないでください。
スクリーンショット 2025-02-26 15.24.50

デプロイが完了したら本番環境のサイトにアクセスすることが可能です。

接続確認

本番環境のドメインにアクセスし、以下の画面が表示されたら成功です。また、名前とメールアドレスを入力して本番環境のSupabaseに接続されるかを確認してみます。
スクリーンショット 2025-02-26 19.09.22

無事Userレコードが作成されているのがわかります!(スキーマ上、同一のemailでは作成できないので注意)
スクリーンショット 2025-02-26 19.15.08

これにて、以下の画像の構成のように、開発環境ではコンテナ上のローカルSupabaseに接続し、本番環境では本番Supabaseへ接続できるような構成が完成しました。

スクリーンショット 2025-02-24 15.03.38

おわりに

今回はNext.jsアプリケーションをVercel + Supabase + Prismaの構成での本番環境と開発環境(ローカル)の環境構築をする方法を解説しました。
色々なドキュメントを横断して構築する必要があったので一つのブログにまとめてみました。
慣れてしまえば1時間ほどでサクッと環境構築ができ、高速な開発体験を得ることができるので今後もこの構成で個人開発などをしていきたいと思います。
以上、どなたかの参考になれば幸いです。

参考

https://www.prisma.io/docs/getting-started/quickstart-sqlite
https://www.prisma.io/docs/orm/overview/databases/supabase
https://supabase.com/docs/guides/database/prisma

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.