1. HOME
  2. ブログ
  3. エンジニアリング
  4. Next.js+Postgres+PrismaでDB設計をしよう!

BLOG

ブログ

エンジニアリング

Next.js+Postgres+PrismaでDB設計をしよう!

はじめに

本章では、データベースを中心にプロジェクトをセットアップしていきます。

  • Vercelデプロイ
  • Vercel Posgres
  • Prisma

を設定していきます。

設定対象は以下の図のようになります。

動画で学びたい方はこちらから!

チュートリアルの全体像

本チュートリアルを通じて学べる内容は以下のようになります。

  1. Next.jsの開発環境をセットアップ
  2. 画面デザインしながら基礎を学ぼう
  3. App Routerを理解して使ってみよう
  4. Next.js+Postgres+PrismaでDB設計
  5. サーバコンポーネントでデータ取得
  6. サーバアクションでデータ変更
  7. Vercel Blobで画像アップロード実装
  8. Suspenseでローディングをリッチに
  9. Zodを使ってバリデーション実装
  10. useActionStateでローディング実装
  11. Auth.js v5で認証機能導入
  12. Route HandlersでAPIを設計

GitHub設定

GitHubアカウント作成

GitHubアカウントを持っていない方は、こちらから作成してください。

レポジトリ作成

右上の「➕」ボタンを選択して、「New Repository」を選択

レポジトリ情報を記入します。

「Repository name」は、 inusta-next としましょう。

上の画像の入力項目通りに記入できたら、「Create repository」をクリックします。

レポジトリが作成できました。

こちらにソースコードをプッシュしましょう。

まずは作成したGitHubレポジトリとソースコードを関連づけます。

「git remote add origin …」コマンドをコピペして実行してください。

git remote add origin git@github.com:{GitHubのユーザ名}/inusta-next.git

続いて、コードをプッシュしています。

以下のコマンドを実行してください。

git push -u origin main

Vercel設定

アカウント作成

https://vercel.com/signup

こちらからアカウントを作成します。

Plan Typeは「Hobby」を選択します。

Your Nameに、あなたの名前を入力してください。

「Continue」を押すと、連携するGitプロバイダを聞かれるので、「Continue with GitHub」を選択しましょう。

アカウントが作成できると、以下のような画面に移動します。

プロジェクト作成

それでは、プロジェクトを作成していきましょう。

GitHubとの連携設定を行います。

先ほど、GitHubレポジトリを作成したアカウントを選択してください。

「Install」ボタンをクリックしましょう。

連携が完了すると、GitHubレポジトリが表示されます。

「Import」ボタンを押します。

そのまま、「Deploy」ボタンを押しましょう。

しばらく待つと、デプロイされます!

Vercel Postgres導入

Vercel Postgres作成

Storageタブを選択します。

Postgresの「Create」をクリックします。

項目を入力して、「Create」ボタンを押しましょう。

Connect先を聞かれるので、先ほど作成した「inusta-next」プロジェクトを選択します。

環境変数設定

まずは、環境変数ファイルを作成しましょう。

「inusta-next」プロジェクト直下に .env ファイルを作成してください。

続いて、先ほど作成したPostgresの画面に移動して、 .env のタブをクリックしてください。

「Copy Snippet」で環境変数をコピーできるので、 .envファイルに貼り付けます。

.envファイル

Prisma導入

インストール

npm install prisma --save-dev
npm install @prisma/client

初期化

npx prisma init

prisma/schema.prisma が作成されます。

スキーマ定義

prisma/schema.prisma

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

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

model Post {
  id        String    @id @default(cuid())
  image     String
  caption   String
  user      User      @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId    String
  comments  Comment[]
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt

  @@map(name: "posts")
}

model Comment {
  id        String   @id @default(cuid())
  text      String
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId    String
  post      Post     @relation(fields: [postId], references: [id], onDelete: Cascade)
  postId    String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@map(name: "comments")
}

model User {
  id          String    @id @default(cuid())
  name        String
  email       String    @unique
  password    String
  image       String?
  description String?
  posts       Post[]
  comments    Comment[]
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt

  @@map(name: "users")
}

型ファイル生成

npx prisma generate

スキーマをデータベースに反映

npx prisma db push

Prisma Studio

npx prisma studio

http://localhost:5555にアクセスするとデータベースの中身が見られます。

テストデータ作成

シード定義

データベースの中身が空なので、テストデータを入れます。

prisma/seed.tsを作成して以下のように記述します。

import { PrismaClient } from "@prisma/client";
import bcrypt from "bcrypt";

const prisma = new PrismaClient();
async function main() {
	const bcryptedPassword = await bcrypt.hash("password", 10);
	const images = [...Array(16)]
		.map((_, i) => i + 1)
		.map((i) => `/dogs/dog_${i}.jpg`);
	const users = [...Array(10)]
		.map((_, i) => i + 1)
		.map((i) => {
			return {
				name: `user+${i}`,
				email: `user+${i}@example.com`,
				password: bcryptedPassword,
				image: images[Math.floor(Math.random() * images.length)],
				description: "こんにちは。よろしくお願いします🐕",
			};
		});

	const createPosts = () => {
		return [...Array(10)].map(() => {
			return {
				image: images[Math.floor(Math.random() * images.length)],
				caption: "かわいいワンちゃん🐶",
			};
		});
	};

	const createComments = (userId: string, postId: string) => {
		const comments = [
			"かわいい😍",
			"可愛い❤️",
			"すてき👏",
			"素敵✨",
			"ナイス🙌",
			"いいね👍",
			"👏👏👏",
			"🎉🎉🎉",
			"🍾🍾🍾",
			"🙌🙌🙌",
		];
		return {
			text: comments[Math.floor(Math.random() * comments.length)],
			userId,
			postId,
		};
	};

	for (const user of users) {
		await prisma.user.upsert({
			where: { email: user.email },
			update: {},
			create: {
				...user,
				posts: {
					create: createPosts(),
				},
			},
		});
	}

	const createdUsers = await prisma.user.findMany();
	const createdPosts = await prisma.post.findMany();
	const comments = createdPosts.flatMap((post) => {
		return createdUsers
			.map((user) => {
				return {
					postId: post.id,
					userId: user.id,
				};
			})
			.map((ids) => {
				return createComments(ids.userId, ids.postId);
			});
	});

	await prisma.comment.createMany({
		data: comments,
	});
}

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

シード実行

package.json に以下の記述を加えます。

"prisma": {
  "seed": "ts-node prisma/seed.ts"
}

以下のコマンドでシードを実行します。

npx prisma db seed

Prisma Studioを開いてみましょう。

テストデータが作成されているはずです。

prismaクライアント設定

lib/prisma.tsを作成して以下のように記述します。

import { PrismaClient } from "@prisma/client";

let prisma: PrismaClient;

if (process.env.NODE_ENV === "production") {
  prisma = new PrismaClient();
} else {
  const globalWithPrisma = global as typeof globalThis & {
    prisma: PrismaClient;
  };
  if (!globalWithPrisma.prisma) {
    globalWithPrisma.prisma = new PrismaClient();
  }
  prisma = globalWithPrisma.prisma;
}

export default prisma;

これで lib/prisma.tsをインポートするだけでどこでもDBアクセスができるようになりました。

まとめ

以上、データベースのセットアップでした!

次回からは、データを取得して画面に表示してみましょう!

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

関連記事