Prisma 中文文档 下载 App

Next.js + Prisma 完整集成指南

项目初始化

Prisma 官方提供了 Next.js 脚手架:

npx create-prisma@latest my-next-app --template next --provider postgres --no-deploy

这会创建一个完整的 Next.js + Prisma 项目,包含:

手动添加到现有 Next.js 项目

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

PrismaClient 全局单例(开发热重载必备)

Next.js 开发模式用 HMR(热模块替换),每次文件变更会重新执行模块。这会导致每次热重载都创建一个新 PrismaClient 实例,连接池快速耗尽。

必须把 PrismaClient 做成全局单例:

// src/lib/prisma.ts
import { PrismaClient } from '@prisma/client'

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined
}

export const prisma =
  globalForPrisma.prisma ??
  new PrismaClient({
    log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
  })

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

然后在任何需要数据库的地方:

import { prisma } from '@/lib/prisma'

Server Components 里查询(App Router)

Next.js 13+ App Router 的 Server Components 天然支持 async/await,可以直接在组件里查询:

// app/users/page.tsx
import { prisma } from '@/lib/prisma'
import UserCard from './UserCard'

export default async function UsersPage() {
  const users = await prisma.user.findMany({
    include: { posts: true },
    orderBy: { createdAt: 'desc' },
  })

  return (
    <div>
      <h1>用户列表</h1>
      {users.map(user => (
        <UserCard key={user.id} user={user} />
      ))}
    </div>
  )
}

Server Components 在服务器端执行,可以直接用 await prisma.user.findMany()。不需要 $connect()——Prisma Client 懒连接,第一次查询自动建立连接。

Server Actions 写入数据

Next.js Server Actions 是处理表单提交的推荐方式:

// app/actions.ts
'use server'

import { prisma } from '@/lib/prisma'
import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'

export async function createUser(formData: FormData) {
  const email = formData.get('email') as string
  const name = formData.get('name') as string

  await prisma.user.create({
    data: { email, name },
  })

  revalidatePath('/users')
  redirect('/users')
}
// app/users/new/page.tsx
import { createUser } from '../actions'

export default function NewUserPage() {
  return (
    <form action={createUser}>
      <input name="email" type="email" required />
      <input name="name" />
      <button type="submit">创建</button>
    </form>
  )
}

API Route 里用 Prisma

// app/api/users/route.ts
import { NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'

export async function GET() {
  const users = await prisma.user.findMany()
  return NextResponse.json(users)
}

export async function POST(request: Request) {
  const body = await request.json()
  const user = await prisma.user.create({ data: body })
  return NextResponse.json(user, { status: 201 })
}

Vercel 部署注意

Vercel Serverless Functions 有以下特点:

配置 Pre-build Command

在 Vercel 项目设置里:

Prisma Postgres 自动集成

如果用 Prisma Postgres(官方托管数据库),Vercel 可以直接自动注入环境变量——在 Vercel 项目设置里连一下就好,不需要手动配 DATABASE_URL。

连接池问题

如果数据库直连 Vercel 出现"连接过多"或握手超时:

  1. 确认用了 DIRECT_URL 绕过连接池跑迁移
  2. 考虑用 Prisma Accelerate(官方连接池服务)或 PgBouncer
  3. 检查数据库的最大连接数设置

Next.js + Prisma 模板

Prisma 官方维护了几个 Next.js 示例仓库,覆盖常见场景(搜索 prisma-examples GitHub 仓库):