🔨

無料でシュッとWebアプリを公開するため最初にする作業まとめ(Next.js App Router+Prisma ORM+Supabase)

2024/12/11に公開

こんにちは。わこー@funwarioisii です。

タイトルにあるスタックでクソアプリを作り散らかしています。
この記事を書きながらも、コマンドの動作確認も兼ねたクソアプリクラフトに勤しんでいます。

毎回微妙に調べて直したりしていて大変だったのですが、工程をまとめたので共有します。
多分順番にやれば15分前後でWebサービスを無料で公開できるはずです。

事前準備や想定

  • VercelやSupabaseのアカウント作成済み
  • VercelへのデプロイはGitHubで出来る

また、私は普段 bun を使っているので、他のパッケージマネージャーを利用されている方は適宜読み替えてください。

ローカルでのNext.jsプロジェクトの作成

Next.jsのテンプレートを展開してくれるコマンドを使ってプロジェクトを作成します。

bunx create-next-app@latest sample-pj && cd sample-pj

コマンド実行後いくつか質問されますが、プロジェクト名以外は基本的にデフォルトを想定しています。
特に何かを変えてあとに続くのセットアップで躓くことはないと思います。

Supabaseのセットアップ

Supabaseにアクセスし、新規プロジェクトを作成します。
プロジェクト作成時に設定するパスワードは、データベースのパスワードとしても使用されるため、控えておく必要があります。

Prismaのセットアップ

パッケージの追加

bun a -D prisma

https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql

スキーマ定義

mkdir prisma
touch prisma/schema.prisma

prisma/schema.prisma に以下を書きます。
env() としている環境変数は次のセクションで埋められます。

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

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

model User {
  id String @id @default(cuid())
}

PrismaとSupabaseの接続設定(ハマりポイント)

Supabaseを使用する場合、直接PostgreSQLに接続する場合と異なり、接続先について注意が必要です。
具体的には、以下の2つのモードを使い分ける必要があります。

  • アプリケーション実行時:Transaction mode
  • スキーマ変更時:Session mode

設定は簡単で環境変数に値を入れればよいです。

touch .env

として、.env に書き込みます。

入力すべきURLの取得方法は次の説で説明しますが、次のように書くことになります。

DATABASE_URL=...  # Transaction mode用
DIRECT_URL=...    # Session mode用

Database URL(transaction mode)は次の形式
postgres://[db-user].[project-ref]:[db-password]@aws-0-[aws-region].pooler.supabase.com:6543/[db-name]?pgbouncer=true&connection_limit=1

Direct URL(Session mode)は次の形式
postgres://[db-user].[project-ref]:[db-password]@aws-0-[aws-region].pooler.supabase.com:5432/[db-name]

になります。2つのURLはポート番号やクエリパラメーターが違います。
これらのURLは、Supabaseのダッシュボードから取得できます。

Database URLの取得

  1. プロジェクトページを開く
  2. 画面上部(ヘッダー部)の Connect をクリック
  3. モーダル / Connection Stringタブ内の下部から Database URL として Transaction pooler に書かれている値を、Direct URLとして Session pooler に書かれている値を取得。
  4. 先程の .env ファイルに「パスワードを入れる」「Direct URLにはクエリを書き足す」をして追記

DBの初期化

bunx 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:6543"

Supabase の画面上で User テーブルが作成できたことが確認できます。

Next.jsからPrismaでSupabaseにつなぐ

DBにつなぐためのクライアントを書くファイルを作ります。

mkdir src/lib
touch src/lib/prisma.ts

そこに次のように書きます。

// https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/nextjs-prisma-client-dev-practices
import { PrismaClient } from "@prisma/client";

const prismaClientSingleton = () => {
  return new PrismaClient();
};

declare const globalThis: {
  prismaGlobal: ReturnType<typeof prismaClientSingleton>;
} & typeof global;

const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();

export { prisma };

if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;

データを表示するコードとして次の中身をsrc/app/page.tsxに書きます。

import { prisma } from "@/lib/prisma";

export default async function Home() {
  const users = await prisma.user.findMany();

  return (
    <div>
      {JSON.stringify(users, null, 2)}
    </div>
  );
}

データを何も入れてなければ [] が表示されるはずです。
ここまででローカルでの開発環境は整いました。

VercelでWebサービスとして公開する

Vercelではコードをアップロードすると、ビルドしてデプロイしてくれます。
Vercelを使ってプロジェクトを作成しているとGitHubと連携して、pushされたときにその処理が走る設定が一般的な気がします。
この記事では始めやすさのためにCLIを使った方法を記述しています。

Vercel でビルドする

Vercelでビルドする場合は、next build より前に prisma の関連ファイルを出力する必要があります。

https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/vercel-caching-issue

なので、次のように設定します。

touch vercel.json

vecel.json は次のように書きます。

{
  "buildCommand": "bun run prisma:generate && bun run build"
}

また、package.json の scripts にコマンドを追記します

{
  ...,
  "scripts": {
    ...,
    "prisma:generate": "prisma generate"
  },
}

GitHubなどと連携していればここで push すると動作が確認できるはずです。

CLIからデプロイする

簡単に確認するため、CLIからのデプロイ方法を紹介します。

vercelコマンドを入れて実行します

bun i -g vercel
vercel --prod

Production URLがログで流れてきて、動作が確認できます!

おわりに

一旦まとめましたが、若いサービスやフレームワークなのですぐ変わることがあると思います。
更新性はあるけど雑なものとしてこちらもリンクしておきます。
https://scrapbox.io/funwarioisii/Next.js(AppRouter)+Prisma+supabaseセットアップ

Discussion