跳到主要内容

如何在 TanStack Start 中使用 Prisma ORM

10 分钟

介绍

Prisma ORM 简化了数据库交互,而 TanStack Start 提供了一个强大的框架用于构建现代 React 应用。与 Prisma Postgres 结合使用,它们通过类型安全的查询和高效的数据管理,提供了无缝的全栈开发体验。

本指南将引导您从头开始在 TanStack Start 项目中集成 Prisma ORM 和 Prisma Postgres 数据库。

先决条件

在开始本指南之前,请确保您已安装

  • Node.js 18+
  • 一个 Prisma Postgres 数据库(或任何 PostgreSQL 数据库)

步骤 1:初始化您的 TanStack Start 项目

首先,创建一个新的 TanStack Start 项目。在您想要创建项目的目录中,运行以下命令

mkdir tanstack-start-prisma
cd tanstack-start-prisma
npm init -y

这将创建一个名为 tanstack-start-prisma 的新文件夹,导航进入该文件夹,并初始化一个新的 Node.js 项目。

在您的 IDE 中打开该目录,并创建一个包含以下配置的 tsconfig.json 文件

tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"moduleResolution": "Bundler",
"module": "ESNext",
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true
}
}

我们还需要一个 .gitignore 文件,现在就来设置它

.gitignore
node_modules
.env

接下来,安装 TanStack Router 和 Vinxi,因为 TanStack Start 当前需要它们

npm install @tanstack/react-start @tanstack/react-router vinxi

我们还需要 React、Vite React 插件和 TypeScript

npm install react react-dom
npm install --save-dev @vitejs/plugin-react vite-tsconfig-paths
npm install --save-dev typescript @types/react @types/react-dom

更新您的 package.json 以使用 Vinxi 的 CLI。添加 "type": "module" 并修改脚本以使用 Vinxi 的 CLI

package.json
{
"type": "module",
"scripts": {
"dev": "vinxi dev",
"build": "vinxi build",
"start": "vinxi start"
}
}

然后,创建并配置 TanStack Start 的 app.config.ts 文件

app.config.ts
import { defineConfig } from '@tanstack/react-start/config'
import tsConfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
vite: {
plugins: [
tsConfigPaths({
projects: ['./tsconfig.json'],
}),
],
},
})

为了让 TanStack Start 正常工作,我们需要在 ~/app/ 中创建 5 个文件

  • router.tsx (路由器配置)
  • ssr.tsx (服务器入口点)
  • client.tsx (客户端入口点)
  • routes/__root.tsx (应用的根目录)
  • routes/index.tsx (主页)

router.tsx 配置应用程序的主路由器,包括路由定义和设置

app/router.tsx
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export function createRouter() {
const router = createTanStackRouter({
routeTree,
scrollRestoration: true,
})

return router
}

declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof createRouter>
}
}
注意

您可能会看到一个关于 routeTree.gen.ts 不存在的错误。这是预期行为。它将在您首次运行 TanStack Start 时生成。

ssr.tsx 让我们知道当用户访问给定路由时需要执行哪些路由和加载器

app/ssr.tsx
import {
createStartHandler,
defaultStreamHandler,
} from '@tanstack/react-start/server'
import { getRouterManifest } from '@tanstack/react-start/router-manifest'

import { createRouter } from './router'

export default createStartHandler({
createRouter,
getRouterManifest,
})(defaultStreamHandler)

client.tsx 初始化客户端逻辑以处理浏览器中的路由

app/client.tsx
import { hydrateRoot } from "react-dom/client";
import { StartClient } from "@tanstack/react-start/client";
import { createRouter } from "./router";

const router = createRouter();

hydrateRoot(document, <StartClient router={router} />);

routes/__root.tsx 定义了整个应用程序的根路由和全局 HTML 布局

app/routes/__root.tsx
import type { ReactNode } from "react";
import {
Outlet,
createRootRoute,
HeadContent,
Scripts,
} from "@tanstack/react-router";

export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: "utf-8",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
},
{
title: "Prisma TanStack Start Demo",
},
],
}),
component: RootComponent,
});

function RootComponent() {
return (
<RootDocument>
<Outlet />
</RootDocument>
);
}

function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
return (
<html>
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
);
}

routes/index.tsx 是应用程序的主页

app/routes/index.tsx
import { createFileRoute } from "@tanstack/react-router";

export const Route = createFileRoute("/")({
component: Home,
});

function Home() {
return (
<div>
<h1>Posts</h1>
</div>
);
}

现在,运行

npm run dev

这将生成 routeTree.gen.ts 文件并解决所有路由错误。

您的文件树应如下所示

.
├── app/
│ ├── routes/
│ │ ├── __root.tsx
│ │ └── index.tsx
│ ├── client.tsx
│ ├── router.tsx
│ ├── routeTree.gen.ts
│ └── ssr.tsx
├── .gitignore
├── app.config.ts
├── package-lock.json
├── package.json
└── tsconfig.json

步骤 2:安装和配置 Prisma ORM

接下来,我们需要在项目中安装和设置 Prisma ORM。首先,让我们安装 Prisma CLI。

2.1 安装 Prisma ORM 并定义您的模型

首先,安装必要的依赖项。在项目根目录中,运行

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

Prisma CLI 现在已安装。

现在,运行以下命令并按照提示设置 Prisma

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

此命令执行以下操作

  • 创建一个包含 schema.prisma 文件的 prisma 目录。
  • 创建一个 Prisma Postgres 数据库。
  • 在项目根目录创建一个包含 DATABASE_URL.env 文件。
  • 将生成的 Prisma Client 输出目录定义为 app/generated/prisma

schema.prisma 中,为我们的 Posts 创建一个模型,并将生成器更改为使用 prisma-client 提供程序

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

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
}

要迁移您的数据库,运行

npx prisma migrate dev --name init

这会做三件事

  • prisma/migrations 目录中创建一个新的 SQL 迁移文件。
  • 针对数据库执行 SQL 迁移文件。
  • 在底层运行 prisma generate,这将安装 @prisma/client 包,并根据您的模型生成定制的 Prisma Client API。

要查看您的数据库,运行

npx prisma studio

选择 Post 表并添加一条记录。

信息

除了使用 Prisma Studio,您还可以使用以下命令为数据库注入数据。有关更多信息,请参阅Prisma Seed

我们还不能在应用程序中看到帖子,所以让我们解决这个问题。

2.2 在 index.tsx 中获取和显示数据

让我们设置 index.tsx 来获取我们添加到数据库中的帖子。首先,导入必要的模块

app/routes/index.tsx
import { PrismaClient } from "../generated/prisma";
import { createServerFn } from "@tanstack/react-start";

创建 Prisma Client 实例

app/routes/index.tsx
const prisma = new PrismaClient();

使用 TanStack Start 的 createServerFn 创建一个服务器函数,使用 .findMany() 从数据库中获取帖子

app/routes/index.tsx
const getPosts = createServerFn({ method: "GET" }).handler(async () => {
return prisma.post.findMany();
});

TanStack Start 允许在 createFileRoute 函数中使用加载器函数在加载时运行函数。使用此代码在加载时获取帖子

app/routes/index.tsx
export const Route = createFileRoute("/")({
component: Home,
loader: () => {
return getPosts();
},
});

使用 Route.useLoaderData() 在主组件中存储加载器返回的响应

app/routes/index.tsx
function Home() {
const posts = Route.useLoaderData();

return (
<div>
<h1>Posts</h1>
</div>
);
}

遍历帖子并以列表形式显示它们

app/routes/index.tsx
function Home() {
const posts = Route.useLoaderData();

return (
<div>
<h1>Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</li>
))}
</ul>
</div>
);
}

此设置将在页面上显示帖子,这些帖子直接从数据库中获取。

后续步骤

您已成功将 Prisma ORM 与 TanStack Start 集成,创建了一个无缝的全栈应用程序。以下是一些后续建议

  • 扩展您的 Prisma 模型以处理更复杂的数据关系。
  • 实现额外的 CRUD 操作以增强应用程序的功能。
  • 探索 Prisma 和 TanStack Start 的更多功能以加深理解。
  • 查看 Prisma Postgres,了解如何扩展您的应用程序。

更多信息


与 Prisma 保持联系

通过以下方式与我们联系,继续您的 Prisma 之旅 我们的活跃社区。保持知情,参与其中,并与其他开发者协作

我们非常重视您的参与,并期待您成为我们社区的一部分!