Next.js+Postgres+PrismaでDB設計をしよう!
目次
はじめに
本章では、データベースを中心にプロジェクトをセットアップしていきます。
- Vercelデプロイ
- Vercel Posgres
- Prisma
を設定していきます。
設定対象は以下の図のようになります。
動画で学びたい方はこちらから!
チュートリアルの全体像
本チュートリアルを通じて学べる内容は以下のようになります。
- Next.jsの開発環境をセットアップ
- 画面デザインしながら基礎を学ぼう
- App Routerを理解して使ってみよう
- Next.js+Postgres+PrismaでDB設計
- サーバコンポーネントでデータ取得
- サーバアクションでデータ変更
- Vercel Blobで画像アップロード実装
- Suspenseでローディングをリッチに
- Zodを使ってバリデーション実装
- useActionStateでローディング実装
- Auth.js v5で認証機能導入
- 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設定
アカウント作成
こちらからアカウントを作成します。
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アクセスができるようになりました。
まとめ
以上、データベースのセットアップでした!
次回からは、データを取得して画面に表示してみましょう!
この記事へのコメントはありません。