跳至主要内容

如何在 Next.js 应用程序中嵌入 Prisma Studio

15 分钟

可以使用 @prisma/studio-core 包将 Prisma Studio 直接嵌入到您的 Next.js 应用程序中。本指南将引导您完成设置,以便您可以从应用程序内部管理数据库,而无需单独运行 Prisma Studio。

完成本指南后,您将拥有一个嵌入 Prisma Studio 的 Next.js 应用程序,允许您直接从应用程序界面浏览和编辑数据库

Prisma Studio embedded in Next.js app

在以下场景中,嵌入 Prisma Studio 会很有用:

  • 构建用于编辑数据的快速管理仪表板
  • 支持每个用户都有自己的数据库的多租户应用程序
  • 为用户提供查看和编辑数据的便捷方式
注意

可嵌入的 Prisma Studio免费的,并采用 Apache 2.0 许可证。

✔️ 可免费用于生产环境 ⚠️ Prisma 品牌必须保持可见且不变 🔐 如需删除品牌或了解即将推出的仅限合作伙伴的功能,请联系 partnerships@prisma.io

目前,嵌入式 Prisma Studio 支持 Prisma Postgres,即将支持更多数据库。

先决条件

  • Node.js 20+
  • 基本的 React 和 Next.js 知识
  • 一个 Prisma Postgres 数据库

1. 设置 Next.js

首先,在您要构建应用程序的目录中创建一个新的 Next.js 项目

npx create-next-app@latest nextjs-studio-embed

系统将提示你回答一些关于项目的问题。选择所有默认值。

信息

供参考,它们是

  • TypeScript
  • ESLint
  • Tailwind CSS
  • 没有 src 目录
  • App Router
  • Turbopack
  • 选择默认导入别名

然后,导航到项目目录

cd nextjs-studio-embed

2. 设置 Prisma ORM 和 Prisma Postgres

2.1. 安装 Prisma 依赖项

安装所需的 Prisma 包

npm install prisma tsx @types/pg --save-dev
npm install @prisma/extension-accelerate @prisma/client @prisma/adapter-pg dotenv pg
信息

如果你使用的是其他数据库提供程序(MySQL、SQL Server、SQLite),请安装相应的驱动程序适配器包,而不是 @prisma/adapter-pg。有关更多信息,请参阅 数据库驱动程序

2.2. 使用 Prisma Postgres 初始化 Prisma

在您的项目中初始化 Prisma 并创建 Prisma Postgres 数据库

npx prisma init --db --output ../app/generated/prisma
信息

在设置 Prisma Postgres 数据库时,您需要回答几个问题。选择离您最近的区域和数据库的名称,例如“我的 __________ 项目”

prisma init --db 命令会创建

  • 一个包含 schema.prisma 文件的 prisma/ 目录
  • 一个用于配置 Prisma 的 prisma.config.ts 文件
  • 一个新的 Prisma Postgres 数据库
  • 一个包含 DATABASE_URL.env 文件
  • Prisma Client 的输出目录 app/generated/prisma

2.3. 定义数据库架构

打开 prisma/schema.prisma 并替换为以下内容:

prisma/schema.prisma
generator client {
provider = "prisma-client"
output = "../app/generated/prisma"
}

datasource db {
provider = "postgresql"
}


model User {
id Int @id @default(autoincrement())
name String
email String @unique
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
}

2.4 将 dotenv 添加到 prisma.config.ts

要访问 .env 文件中的变量,它们可以由您的运行时加载,或者通过使用 dotenv 加载。在 prisma.config.ts 顶部包含 dotenv 的导入

import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
datasource: {
url: env('DATABASE_URL'),
},
});

2.5. 将架构应用到数据库

生成 Prisma Client 并应用架构

npx prisma migrate dev --name init
npx prisma generate

这将在 Prisma Postgres 数据库中创建表并生成 Prisma Client。

2.6. 为数据库播种(可选)

创建一个 seed 文件以添加一些示例数据。在 prisma 文件夹中创建一个 seed.ts 文件并添加以下代码:

prisma/seed.ts
import { PrismaClient } from '../app/generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'

const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
})

const prisma = new PrismaClient({
adapter,
})

async function main() {
// Create users
const user1 = await prisma.user.create({
data: {
name: 'Alice Johnson',
email: 'alice@example.com',
},
})

const user2 = await prisma.user.create({
data: {
name: 'Bob Smith',
email: 'bob@example.com',
},
})

// Create posts
await prisma.post.create({
data: {
title: 'Getting Started with Next.js',
content: 'Next.js is a powerful React framework...',
published: true,
authorId: user1.id,
},
})

await prisma.post.create({
data: {
title: 'Database Management with Prisma',
content: 'Prisma makes database management easy...',
published: false,
authorId: user2.id,
},
})

console.log('Database seeded successfully!')
}

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

将 seed 脚本添加到 prisma.config.ts

prisma.config.ts
import 'dotenv/config';
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
seed: `tsx prisma/seed.ts`,
},
datasource: {
url: env('DIRECT_URL'),
},
});

运行种子脚本

npx prisma db seed

3. 在应用程序中设置嵌入式 Prisma Studio

现在您已经设置好 Prisma ORM 和 Prisma Postgres,可以将 Prisma Studio 嵌入到您的 Next.js 应用程序中。

3.1. 安装 Prisma Studio Core 包

安装提供可嵌入组件的 @prisma/studio-core

npm install @prisma/studio-core
注意

如果您在安装 @prisma/studio-core 时遇到依赖项解析错误,可以使用以下命令强制安装:

npm install @prisma/studio-core --force

如果您使用的是 yarn、pnpm 或其他包管理器,请使用适用于您工具的等效标志。

@prisma/studio-core 提供了 Studio,这是一个 React 组件,用于渲染您的数据库的 Prisma Studio。Studio 组件接受一个执行器,它访问后端中的自定义端点。后端使用您的 API 密钥识别正确的 Prisma Postgres 实例并将 SQL 查询发送到该实例。

3.2. 创建 Studio 包装器组件

创建一个 components 文件夹并添加一个名为 StudioWrapper.tsx 的新文件。此文件将包装 Studio 组件并提供一致的布局

components/StudioWrapper.tsx
'use client';
import "@prisma/studio-core/ui/index.css";
import { ReactNode } from 'react';

interface StudioWrapperProps {
children: ReactNode;
}

export default function StudioWrapper({ children }: StudioWrapperProps) {
return (
<div className="min-h-screen bg-gray-50">
<header className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center py-4">
<h1 className="text-2xl font-bold text-gray-900">
Database Studio
</h1>
<div className="text-sm text-gray-500">
Powered by Prisma Studio
</div>
</div>
</div>
</header>
<main className="max-w-7xl mx-auto">
<div className="h-[calc(100vh-80px)]">
{children}
</div>
</main>
</div>
);
}

3.3. 创建一个 API 端点以将 SQL 查询发送到 Prisma Studio

接下来,设置一个 Prisma Studio 可以与之通信的后端端点。此端点接收来自嵌入式 Studio UI 的 SQL 查询,将其转发到您的 Prisma Postgres 数据库,然后将结果(或错误)返回到前端。

为此,在 app 目录中创建一个名为 api 的新文件夹。在其中,添加一个包含 route.ts 文件的 studio 文件夹。此文件将处理发送到 /api/studio 的所有请求,并充当前端 Studio 组件和后端数据库之间的桥梁

app/api/studio/route.ts
import "dotenv/config"
import { createPrismaPostgresHttpClient } from "@prisma/studio-core/data/ppg";
import { serializeError } from "@prisma/studio-core/data/bff";

const CORS_HEADERS = {
"Access-Control-Allow-Origin": "*", // Change to your domain in production
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};

// Use dynamic rendering for database operations
export const dynamic = "force-dynamic";

export async function GET() {
return Response.json(
{ message: "Studio API endpoint is running" },
{ headers: CORS_HEADERS }
);
}

export async function POST(request: Request) {
try {
const body = await request.json();
const query = body.query;

if (!query) {
return Response.json([serializeError(new Error("Query is required"))], {
status: 400,
headers: CORS_HEADERS,
});
}

const url = process.env.DATABASE_URL;
if (!url) {
const message = "❌ Environment variable DATABASE_URL is missing.";
return Response.json([serializeError(new Error(message))], {
status: 500,
headers: CORS_HEADERS,
});
}

const [error, results] = await createPrismaPostgresHttpClient({
url,
}).execute(query);

if (error) {
return Response.json([serializeError(error)], {
headers: CORS_HEADERS,
});
}

return Response.json([null, results], { headers: CORS_HEADERS });
} catch (err) {
return Response.json([serializeError(err)], {
status: 400,
headers: CORS_HEADERS,
});
}
}

// Handle preflight requests for CORS
export async function OPTIONS() {
return new Response(null, { status: 204, headers: CORS_HEADERS });
}

3.4. 创建主 Studio 页面

打开 app/page.tsx 文件并替换现有代码以使用以下内容渲染嵌入式 Studio:

app/page.tsx
'use client';

import dynamic from "next/dynamic";
import { createPostgresAdapter } from "@prisma/studio-core/data/postgres-core";
import { createStudioBFFClient } from "@prisma/studio-core/data/bff";
import { useMemo, Suspense } from "react";
import StudioWrapper from "@/components/StudioWrapper";

// Dynamically import Studio with no SSR to avoid hydration issues
const Studio = dynamic(
() => import("@prisma/studio-core/ui").then(mod => mod.Studio),
{
ssr: false
}
);

// Loading component
const StudioLoading = () => (
<div className="flex items-center justify-center h-full">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
<p className="mt-4 text-gray-600">Loading Studio...</p>
</div>
</div>
);

// Client-only Studio component
const ClientOnlyStudio = () => {
const adapter = useMemo(() => {
// Create the HTTP client that communicates with our API endpoint
const executor = createStudioBFFClient({
url: "/api/studio",
});

// Create the Postgres adapter using the executor
return createPostgresAdapter({ executor });
}, []);

return <Studio adapter={adapter} />;
};

export default function App() {
return (
<StudioWrapper>
<Suspense fallback={<StudioLoading />}>
<ClientOnlyStudio />
</Suspense>
</StudioWrapper>
);
}

3.5. 启动开发服务器并测试嵌入式 Studio

启动您的 Next.js 开发服务器

npm run dev

打开浏览器并访问 https://:3000。您现在应该会在应用程序中看到 Prisma Studio 正在运行

Prisma Studio embedded in Next.js app

以下是需要注意的事项:

  1. Prisma Studio 界面:完整的 Prisma Studio UI 应在您的应用程序布局中呈现。
  2. 您的数据:您定义的 UserPost 表(以及任何种子数据)应该会出现。
  3. 交互功能:
    • 浏览和筛选表中的记录
    • 通过双击单元格来内联编辑值
    • 使用“添加记录”按钮添加新记录
    • 删除不再需要的记录
    • 通过在相关表之间导航来探索关系

通过测试基础知识来验证一切是否正常

  • 单击不同的表以确认数据加载。
  • 更新记录以检查更改是否已保存。
  • 添加新记录并确认它立即出现。
  • 尝试筛选数据以确保查询正确运行。
  • 通过关系导航(例如,查看用户的帖子)以确认关联正常工作。

一旦这些操作按预期工作,您的嵌入式 Prisma Studio 就已设置好并连接到您的 Prisma Postgres 数据库。

后续步骤

此时,您的 Next.js 应用程序中正在运行 Prisma Studio,并连接到您的 Prisma Postgres 数据库。您可以浏览、编辑和管理数据,而无需离开您的应用程序。为了使此设置适用于生产环境,请考虑以下改进:

  1. 添加身份验证:目前,任何可以打开您的应用程序的人都可以访问 Prisma Studio。添加用户身份验证并仅允许特定角色(例如,管理员)使用嵌入式 Studio。您可以通过在运行查询之前检查 /api/studio 端点中的身份验证令牌来完成此操作。

  2. 使用特定于环境的配置:在开发中,您可能需要一个测试数据库,而在生产中,您需要一个单独的实时数据库。更新您的 .env 文件以对每个环境使用不同的 DATABASE_URL 值,并确认您的 /api/studio 端点正在读取正确的值。

  3. 应用自定义样式:Studio 组件附带默认外观。传入您自己的主题并调整颜色、排版或品牌以匹配应用程序的其余部分。这有助于 Studio 感觉像是应用程序的本机部分,而不是独立的工具。

通过添加身份验证、特定于环境的设置和样式,您将从一个工作演示转向一个安全且完善的生产设置。

有关更多模式和示例,请参阅 Prisma Studio Core 演示存储库,其中包括使用 Hono.js 和 React 的替代实现。如果您更喜欢引导式演练,请观看 YouTube 视频:**在您自己的应用程序中使用 Prisma Studio**


与 Prisma 保持联系

通过以下方式与我们保持联系,继续你的 Prisma 之旅: 我们的活跃社区。保持信息灵通,参与其中,并与其他开发人员协作。

我们真诚地感谢你的参与,并期待你成为我们社区的一部分!

© . This site is unofficial and not affiliated with Prisma Data, Inc.