🍣

T3 stackを使ってモダンなWeb開発を行う 〜Prisma × PostgreSQL編〜

2023/10/18に公開

0.はじめに

T3 Stack は、モダンな Web 開発を行うためのフルスタックフレームワークで、以下の 6 つの技術スタックを組み合わせています:

  1. Next.js: フロントエンドの Web アプリケーション開発において、高速かつ効率的な React フレームワークです。

  2. tRPC: サーバーとクライアント間の型安全な通信を提供し、API の定義と使用を簡素化します。

  3. Tailwind CSS: カスタマイズ可能なスタイリングのための CSS フレームワークで、設計のシンプルさと拡張性を兼ね備えています。

  4. TypeScript: 型安全性を提供し、コードの品質向上と開発効率の向上に貢献します。

  5. Prisma: データベースアクセスと ORM(Object-Relational Mapping)を簡素化し、型安全なデータベース操作を実現します。

  6. NextAuth.js: 認証とセッション管理をサポートするライブラリで、ユーザーアカウントの認証を簡単に実装できます。

T3 Stack は、シンプルな設計とモジュール化された構造に基づいており、開発効率を向上させ、コードの品質を高めることを目指しています。型安全性が保証されているため、開発者は安心してコードを記述できます。このフレームワークは、フロントエンド開発の効率向上と品質向上を追求する開発者にとって理想的な選択肢の一つです。

この記事では、実際に T3 stack を使って、アプリケーションを開発していきます。

今回は、Prisma を使用して PostgreSQL に接続し、CRUD 操作を行なっていきます。

Prisma について

Prisma は、データベースアクセスと ORM(Object-Relational Mapping)を簡素化し、モダンなウェブアプリケーションを開発するためのデータベースツールとして人気のあるライブラリです。Prisma は、TypeScript や JavaScript を使用したアプリケーションのバックエンドとデータベースの連携を効率的に行うために設計されています。

PostgreSQL について

PostgreSQL(ポストグレスキューエル)は、オープンソースのリレーショナルデータベース管理システム(RDBMS)です。データはテーブルと呼ばれる構造内に行と列の形式で格納されます。このリレーショナルモデルは、データを整理して関連付けるのに役立ちます。

公式ドキュメント

1.PostgreSQL 用に修正

まずは、PostgreSQL に接続するための設定を行なっていきます。(公式ドキュメント)

schema.prismaを下記のように修正します。

schema.prisma
datasource db {
    provider = "postgresql"
    url       = env("POSTGRES_PRISMA_URL") // uses connection pooling
    directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
}

次に環境変数周りを修正します。

.envファイルに下記を追加します。これを追加すると環境変数の検証をスキップすることができます。

SKIP_ENV_VALIDATION=true

次に、env.mjsを書き換えます。

src/env.mjs
  server:{
-    DATABASE_URL: z
-      .string()
-      .url()
-      .refine(
-        (str) => !str.includes("YOUR_MYSQL_URL_HERE"),
-        "You forgot to change the default URL",
-      ),
+    POSTGRES_PRISMA_URL: z.string().url(),
+    POSTGRES_URL_NON_POOLING: z.string().url(),
  }

  runtimeEnv: {
-    DATABASE_URL: process.env.DATABASE_URL,
+    POSTGRES_PRISMA_URL: process.env.POSTGRES_PRISMA_URL,
+    POSTGRES_URL_NON_POOLING: process.env.POSTGRES_URL_NON_POOLING,
  },

この修正が終われば、この時点でデプロイエラーが解消されるので、デプロイしてみてくださいね。

今回、.env以外の環境変数(.env.development.local)を呼び出したいので、scripts 関係もいじっていきます。(公式ドキュメント)


まずは、dotenv-cli をインストールします。

npm i --dev dotenv-cli

次に、package.jsonの sctipts を修正します。

package.json
  "scripts": {
-    "db:push": "prisma db push",
+    "db:push": "dotenv -e .env.development.local -- prisma db push",
+    "migrate": "dotenv -e .env.development.local -- npx prisma migrate deploy",
  },

これで一旦準備は完了です。

2.Prisma Migrate

設定がおわったら migrate を実行していきます。

Prisma Migrate は、データベーススキーマの変更を記述するためのマイグレーションファイルを生成します。これには新しいテーブルの作成、既存のテーブルの変更、データの移行などが含まれます。

npx dotenv -e .env.development.local -- npx prisma migrate dev --name init

3.動作確認

データベースの設定が終わったので、データベースと接続してみましょう。

ここでは、node.js にて接続していきます。まずは、Prisma クライアントと ts-node のインストールを行います。

npm install @prisma/client 
npm install -D ts-node @types/node

tsconfig.jsonを修正します。

tsconfig.json
+ "scripts": {
+   "ts": npx dotenv -e .env.development.local -- node --loader ts-node/esm,
+ }
+ "ts-node": {
+   "esm": true,
+ }

pack.jsonに追加

pack.json
+  "type": "module"

Read

次に、ts-src/read.tsを作成します。これは、Userテーブルにあるデータを全て取得するプログラムになっています。

ts-src/read.ts
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

async function main() {
  const allUsers = await prisma.user.findMany();
  console.log(allUsers);
}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

早速データベースを読み取っていきたいと思います。

npm run ts ts-src/read.ts

まだデータベースにデータがないので[]が帰ってきます。

Create

次に、ts-src/read.tsをコピーして、ts-src/create.tsをつくり main 関数を下記の通り変更します。

これは、Userテーブルにデータを追加するプログラムになっています。

create.ts
async function main() {
  await prisma.user.create({
    data: {
      name: "Alice",
      email: "alice@prisma.io",
      image: "abc.jpeg",
    },
  });

  const allUsers = await prisma.user.findMany();
  console.log(allUsers, { depth: null });
}

早速データベースにデータを追加したいと思います。

npm run ts ts-src/create.ts

戻り値は、

[
  {
    "id": "clncung8t0000dwtkl6etjral",
    "name": "Alice",
    "email": "alice@prisma.io",
    "emailVerified": null,
    "image": "abc.jpeg"
  }
]

ここで、Vercel Storage でも確認してみましょう。Vercel ダッシュボードに移動して、Choose a tableをクリックし、Userテーブルを選択します。

Vercelダッシュボード

すると、user データが追加されていることがわかります。

Vercelダッシュボード

Update

次に、ts-src/read.tsをコピーして、ts-src/update.tsをつくり main 関数を下記の通り変更します。

※id は先ほど取得した id を書き込んでください

これは、id が一致する user を探し出し、データを更新するプログラムになっています。

update.ts
async function main() {
  const post = await prisma.user.update({
    where: { id: "clncung8t0000dwtkl6etjral" },
    data: { image: "Alice.jpeg" },
  });
  console.log(post);
}

データベースを更新しましょう。

npm run ts ts-src/update.ts

戻り値は、

{
  "id": "clncung8t0000dwtkl6etjral",
  "name": "Alice",
  "email": "alice@prisma.io",
  "emailVerified": null,
  "image": "Alice.jpeg"
}

image のデータが書き換わっていることがわかると思います。

Vercelダッシュボード

Delete

最後に、ts-src/read.tsをコピーして、ts-src/delete.tsをつくり main 関数を下記の通り変更します。

※id は先ほど取得した id を書き込んでください

delete.ts
async function main() {
  const data = await prisma.user.delete({
    where: { id: "clncung8t0000dwtkl6etjral" },
  });
  console.log(data);

  const allUsers = await prisma.user.findMany();
  console.log(allUsers);
}

データを消してみましょう。

npm run ts ts-src/delete.ts

戻り値は、

{
  "id": "clnmpb2pp0000fv6ddo78xjsc",
  "name": "Alice",
  "email": "alice@prisma.io",
  "emailVerified": null,
  "image": "Alice.jpeg"
}

データベースのデータが無くなったので[]が帰ってきます。

Vercelダッシュボード

Prisma × postgreSQL は以上となります。お疲れ様でした。

もし記事があなたのお役に立ったなら、ぜひ「いいね!」ボタンをクリックしてくださいね。

Discussion