Работа с БД
Server Components могут напрямую работать с базой данных.
Prisma
Самый популярный ORM для Next.js.
npm install prisma @prisma/client
npx prisma init
schema.prisma:
model Post {
id Int @id @default(autoincrement())
title String
body String
published Boolean @default(false)
createdAt DateTime @default(now())
}
npx prisma migrate dev
npx prisma generate
Prisma client singleton
lib/db.ts:
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const db = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
Без singleton — много подключений в dev.
Использование
import { db } from '@/lib/db';
export default async function Posts() {
const posts = await db.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
take: 10,
});
return <ul>{posts.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;
}
CRUD
// Create
const post = await db.post.create({ data: { title: 'Новый' } });
// Read
const post = await db.post.findUnique({ where: { id: 1 } });
const posts = await db.post.findMany();
// Update
await db.post.update({ where: { id: 1 }, data: { title: 'Обновлён' } });
// Delete
await db.post.delete({ where: { id: 1 } });
Связи
model User {
id Int @id @default(autoincrement())
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id])
authorId Int
}
Запрос со связью:
const posts = await db.post.findMany({
include: { author: true },
});
const user = await db.user.findUnique({
where: { id: 1 },
include: { posts: true },
});
Транзакции
await db.$transaction([
db.post.create({ data: { title: 'A' } }),
db.post.create({ data: { title: 'B' } }),
]);
Или интерактивно:
await db.$transaction(async (tx) => {
const post = await tx.post.create({ data: { title: 'A' } });
await tx.comment.create({ data: { postId: post.id, text: 'B' } });
});
Drizzle
Лёгкая альтернатива. Меньше магии, больше контроля.
npm install drizzle-orm postgres
npm install -D drizzle-kit
schema.ts:
import { pgTable, serial, text, boolean, timestamp } from 'drizzle-orm/pg-core';
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
body: text('body').notNull(),
published: boolean('published').default(false),
createdAt: timestamp('created_at').defaultNow(),
});
lib/db.ts:
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client, { schema });
Запрос:
const allPosts = await db.select().from(posts);
await db.insert(posts).values({ title: 'Новый', body: 'Текст' });
Prisma vs Drizzle
- Prisma — больше магии, свой DSL, генерация типов, миграции из коробки
- Drizzle — ближе к SQL, лёгкий, типы выводятся из схемы
Оба подходят. Prisma — если хочешь быстрый старт. Drizzle — если хочешь контроль.
Server Components
Прямой доступ к БД — одна из главных фишек. Не нужен API-слой.
export default async function Users() {
const users = await db.user.findMany();
return <UserList users={users} />;
}
Server Actions для мутаций
'use server';
export async function createPost(data: FormData) {
await db.post.create({ data: { title: data.get('title') } });
revalidatePath('/posts');
}
Итоги
- Prisma и Drizzle — популярные ORM
- Singleton для клиента
- Прямой доступ в Server Components
- Server Actions для мутаций
- Транзакции для согласованности
- Связи через
includeилиjoin