🐘

【新機能】Vercel Postgres + Next.js + PrismaでフルスタックWebアプリケーションを作ってみた

2023/05/02に公開
1

はじめに

GWに入り、5日連続のVercelによる新機能の発表が始まりました。早速初日(2023 5/1)からすさまじい機能の発表がありました。

初日に発表されたのは、以下の三つのStorageサービスです。

  1. Vercel Postgres
  2. Vercel KV
  3. Vercel Blob

https://vercel.com/ship

今回はこの中のVercel Postgresを実際に使いながら、ClientからServerまで網羅しためっちゃ簡易的なフルスタックなアプリケーションを、実用性の側面も加味してPrisma + Next.jsで作っていこうと思います。

Vercel CLIの導入

Vercel Postgresのセットアップにあたって、ぶっちゃけなくても開発できますが、Vercel CLIは非常に便利なので導入しましょう。

yarn global add vercel
export PATH=$PATH:~/.yarn/bin

↑↑↑ターミナル開くごとに毎回export PATH...はだるいので、zshrcなどに記載することをお勧めします。

vercel -v
# => Vercel CLI 29.0.3

Vercel Postgresのセットアップ

まず、Vercelのダッシュボードのヘッダーのstorageから進めていきます。
次に、Create Databaseから実際にデータベースを作成していきます。

Create Databaseをクリックすると、下記のスクショのようなStorageサービスを選択を行います。

最後にデータベース名とリージョンを決定して無事完成です。

Vercel Postgresをプロジェクトに紐付ける

ダッシュボード上でプロジェクトとVercel Postgresの接続を行います。

Vercelのプロジェクトが存在しない場合は、Vercel linkコマンドでプロジェクトの作成から行えます。

ここでデータベースのcredential情報が取得できたので、次にローカルに環境変数をプルします。

環境変数をローカルにプルする

下記のコマンドで、先ほど作成したデータベースのcredentail情報をローカルにプルしてきます。

terminal
vercel env pull .env

このコマンドを実行すると、ローカルのプロジェクトに.envファイルが作成されます。また以下のようにいくつかの環境変数が記述されています。

.env
# Created by Vercel CLI
VERCEL="1"
VERCEL_ENV="development"
TURBO_REMOTE_ONLY="true"
NX_DAEMON="false"
VERCEL_URL=""
VERCEL_GIT_PROVIDER=""
VERCEL_GIT_PREVIOUS_SHA=""
VERCEL_GIT_REPO_SLUG=""
VERCEL_GIT_REPO_OWNER=""
VERCEL_GIT_REPO_ID=""
VERCEL_GIT_COMMIT_REF=""
VERCEL_GIT_COMMIT_SHA=""
VERCEL_GIT_COMMIT_MESSAGE=""
VERCEL_GIT_COMMIT_AUTHOR_LOGIN=""
VERCEL_GIT_COMMIT_AUTHOR_NAME=""
VERCEL_GIT_PULL_REQUEST_ID=""
POSTGRES_URL="postgres:~~~~"
POSTGRES_URL_NON_POOLING="postgres:~~~~"
POSTGRES_PRISMA_URL="postgres:~~~~"
POSTGRES_USER="~~~~"
POSTGRES_HOST="~~~~"
POSTGRES_PASSWORD="~~~~"
POSTGRES_DATABASE="~~~~"

Prismaをセットアップ

まずは、必要なパッケージをインストールします。

terminal
yarn add @vercel/postgres
yarn add prisma @prisma/client

次にSchema.prismaでmigrationを定義します。

schema.prisma
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["jsonProtocol"]
}

datasource db {
  provider          = "postgresql"
  url               = env("POSTGRES_PRISMA_URL")
  directUrl         = env("POSTGRES_URL_NON_POOLING")
  shadowDatabaseUrl = env("POSTGRES_URL_NON_POOLING") 

model Post {
  id          Int    @id @default(autoincrement())
  title       String
  description String
}

最後にmigrationを実行したらPrismaのセットアップ完了です。

terminal
npx prisma generate

以上で、PrismaおよびVercel Postgresのセットアップが完了したので、ここからPostのCRUDなAPIを実装していきます。

※ 個人的な好みですがAPI clientの初期化をlibでやっております。

lib/prisma.ts
import { PrismaClient } from "@prisma/client";

export const prisma = new PrismaClient();

API RouteでのAPI実装

基本機能ということで、今回はGetCreateDeleteをAPI Routeで実装いたしました。
各APIは以下のようになっています。
APIとして完全な要件を満たせているわけではありませんが、よかったら参考にしてみてください。

get.ts
import { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "@/lib/prisma";

export default async function handler(
  _request: NextApiRequest,
  response: NextApiResponse
) {
  try {
    const data = await prisma.post.findMany();

    return response.status(200).json({ data });
  } catch (error) {
    return response.status(500).json({ error });
  }
}

create.ts
import { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "@/lib/prisma";

export default async function handler(
  request: NextApiRequest,
  response: NextApiResponse
) {
  const { title, description } = JSON.parse(request.body);

  try {
    const data = await prisma.post.create({
      select: {
        id: true,
        title: true,
        description: true,
      },
      data: {
        title: title,
        description: description,
      },
    });

    return response.status(200).json({ data });
  } catch (error) {
    return response.status(500).json({ error });
  }
}
delete.ts
import { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "@/lib/prisma";

export default async function handler(
  request: NextApiRequest,
  response: NextApiResponse
) {
  const { id } = JSON.parse(request.body);

  try {
    const data = await prisma.post.delete({
      where: {
        id: parseInt(id, 10),
      },
    });

    return response.status(200).json({ data });
  } catch (error) {
    return response.status(500).json({ error });
  }
}

※フロントエンドのソースコード等については、本筋から外れてしまうため割愛いたします。

詳しいソースコードについては以下をご参照ください。
https://github.com/msy7822-ux/vercel-postgres-app#:~:text=/-,vercel-postgres-app,-Public

Vercelにデプロイする

ここから実際にアプリケーションをデプロイしていきます。
基本的には普段通りのVercelデプロイと何ら変わりはありませんが、今回はORMとしてPrismaを採用しているため、ビルド時にprisma generateを実行する必要があります。

package.json
...

 "scripts": {
    "dev": "next dev",
    "build": "prisma generate && prisma db push && next build",
    "start": "next start",
    "lint": "next lint"
  },

...

あとは必要なソースコードをmainにマージすればデプロイが走ります。

まとめ

最後までご覧いただきありがとうございます。

Vercel + Next.jsでバックエンドからフロントエンド、さらにはデプロイまで完結するため、これはもはやWebアプリケーション開発の完成形と言っても過言ではありませんね。
特に、TanStack Query(旧React Query)との相性は抜群かなと思います。
これでもう小規模な開発であれば別でAPIサーバを建てるのも不要になるかもしれないですね。😅

またVercelの残りの発表も気になるところではありますので、楽しみにしたいと思います!!!

参考情報

https://vercel.com/docs/storage/vercel-postgres/using-an-orm
https://vercel.com/docs/storage/vercel-postgres/quickstart
https://www.prisma.io/docs/guides/development-environment/environment-variables
https://github.com/vercel/examples/blob/main/storage/postgres-prisma/

Discussion

MiyaMiya

Schema.prismaに閉じカッコが1つ足りていないようです