Prisma ORMをTanStack Startで使用する方法
はじめに
Prisma ORMはデータベースとのやり取りを簡素化し、TanStack StartはモダンなReactアプリケーションを構築するための堅牢なフレームワークを提供します。Prisma Postgresと組み合わせることで、型安全なクエリと効率的なデータ管理により、シームレスなフルスタック開発体験を提供します。
このガイドでは、Prisma ORMとPrisma PostgresデータベースをTanStack Startプロジェクトにゼロから統合する手順を説明します。
前提条件
1. プロジェクトのセットアップ
まず、新しいTanStack Startプロジェクトを作成します。
このガイドでは、TanStack Startのドキュメントで提供されているものと同じセットアップ手順を使用します。
プロジェクトを作成したいディレクトリで、以下のコマンドを実行します。
mkdir tanstack-start-prisma
cd tanstack-start-prisma
npm init -y
これにより、tanstack-start-prisma
という新しいフォルダが作成され、その中へ移動し、新しいNode.jsプロジェクトが初期化されます。
IDEでディレクトリを開き、以下の設定でtsconfig.json
ファイルを作成します。
{
"compilerOptions": {
"jsx": "react-jsx",
"moduleResolution": "Bundler",
"module": "ESNext",
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true
}
}
また、.gitignore
ファイルも必要なので、今すぐ設定しましょう。
node_modules
.env
app/generated
次に、TanStack Startが現在必要とするTanStack RouterとVinxiをインストールします。
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を使用するように変更します。
{
"name": "tanstack-start-prisma",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "vinxi dev",
"build": "vinxi build",
"start": "vinxi start"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@tanstack/react-router": "^1.119.0",
"@tanstack/react-start": "^1.119.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"vinxi": "^0.5.6"
},
"devDependencies": {
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.3",
"@vitejs/plugin-react": "^4.4.1",
"typescript": "^5.8.3",
"vite-tsconfig-paths": "^5.1.4"
}
}
次に、TanStack Startの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
(ホームページ)
これらのコマンドで作成できます。
mkdir app
touch app/router.tsx
touch app/ssr.tsx
touch app/client.tsx
mkdir app/routes
touch app/routes/__root.tsx
touch app/routes/index.tsx
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
は、ユーザーが特定のルートにアクセスしたときに、どのルートとローダーを実行する必要があるかを知ることができます。
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
は、ブラウザでルートを処理するためのクライアントサイドロジックを初期化します。
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レイアウトを定義します。
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
はアプリケーションのホームページです。
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
ファイルが生成され、ルーティングエラーが解決されます。
ファイルツリーは次のようになります (node_modules
なし)。
.
├── app
│ ├── client.tsx
│ ├── routeTree.gen.ts
│ ├── router.tsx
│ ├── routes
│ │ ├── __root.tsx
│ │ └── index.tsx
│ └── ssr.tsx
├── app.config.ts
├── package-lock.json
├── package.json
└── tsconfig.json
2. Prismaのインストールと設定
2.1. 依存関係のインストール
Prismaを始めるには、いくつかの依存関係をインストールする必要があります。
- Prisma Postgres (推奨)
- その他のデータベース
npm install prisma tsx --save-dev
npm install @prisma/extension-accelerate @prisma/client
npm install prisma tsx --save-dev
npm install @prisma/client
インストール後、プロジェクトでPrismaを初期化します。
npx prisma init --db --output ../app/generated/prisma
Prisma Postgresデータベースを設定する際に、いくつかの質問に答える必要があります。お住まいの地域に最も近いリージョンと、「My __________ Project」のような覚えやすいデータベース名を選択してください。
これにより、以下が作成されます。
schema.prisma
ファイルを含むprisma
ディレクトリ。- Prisma Postgresデータベース。
- プロジェクトルートに
DATABASE_URL
を含む.env
ファイル。 - 生成されたPrisma Clientの
output
ディレクトリ (app/generated/prisma
)。
2.2. Prismaスキーマの定義
schema.prisma
で、投稿用のモデルを作成し、ジェネレータをprisma-client
プロバイダを使用するように変更します。
generator client {
provider = "prisma-client"
output = "../app/generated/prisma"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
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])
}
これにより、User
とPost
の2つのモデルが作成され、これらは一対多の関係にあります。
2.3. Prisma Clientジェネレータの設定
次に、以下のコマンドを実行してデータベーステーブルを作成し、Prisma Clientを生成します。
npx prisma migrate dev --name init
2.4. データベースへのシード
サンプルユーザーと投稿でデータベースを埋めるために、シードデータを追加しましょう。
prisma/
ディレクトリ内にseed.ts
という新しいファイルを作成します。
import { PrismaClient, Prisma } from "../src/generated/prisma/client.js";
const prisma = new PrismaClient();
const userData: Prisma.UserCreateInput[] = [
{
name: "Alice",
email: "alice@prisma.io",
posts: {
create: [
{
title: "Join the Prisma Discord",
content: "https://pris.ly/discord",
published: true,
},
{
title: "Prisma on YouTube",
content: "https://pris.ly/youtube",
},
],
},
},
{
name: "Bob",
email: "bob@prisma.io",
posts: {
create: [
{
title: "Follow Prisma on Twitter",
content: "https://www.twitter.com/prisma",
published: true,
},
],
},
},
];
export async function main() {
for (const u of userData) {
await prisma.user.create({ data: u });
}
}
main();
次に、package.json
を更新して、Prismaにこのスクリプトの実行方法を伝えます。
"prisma": {
"seed": "tsx prisma/seed.ts"
}
シードスクリプトを実行します。
npx prisma db seed
そして、Prisma Studioを開いてデータを確認します。
npx prisma studio
3. PrismaをTanStack Startに統合する
3.1 Prisma Clientを作成する
各ファイルで新しいPrisma Clientインスタンスを作成する代わりに、共有ファイルで単一のインスタンスを作成し、グローバルに使用します。
/lib
ディレクトリと、その中にprisma.ts
ファイルを作成します。このファイルは、Prisma Clientインスタンスを作成およびエクスポートするために使用されます。
Prismaクライアントをこのようにセットアップします。
- Prisma Postgres (推奨)
- その他のデータベース
import { PrismaClient } from "../generated/prisma/client.js";
import { withAccelerate } from "@prisma/extension-accelerate";
const prisma = new PrismaClient().$extends(withAccelerate());
export default prisma;
import { PrismaClient } from "../generated/prisma/client.js";
const prisma = new PrismaClient();
export default prisma;
データベース接続を効率的に管理するために、接続プーラー(Prisma Accelerateなど)を使用することを推奨します。
接続プーラーを使用しない場合は、寿命の長い環境でPrismaClient
をグローバルにインスタンス化することは避けてください。代わりに、リクエストごとにクライアントを作成および破棄して、データベース接続を使い果たさないようにしてください。
3.2 読み込み時にユーザーと投稿を取得する
まず、必要なモジュールをインポートします。次に、createServerFn
関数を使用してサーバー関数を作成します。この関数は、.findMany()
メソッドを使用してデータベースからユーザーを取得します。関連する投稿を取得するにはinclude
オプションを使用します。
import { prisma } from "../lib/prisma";
import { createServerFn } from "@tanstack/react-start";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({
component: Home,
});
const getUsers = createServerFn({ method: "GET" }).handler(async () => {
return prisma.user.findMany({
include: {
posts: true,
},
});
});
function Home() {
return (
<div>
<h1>Posts</h1>
</div>
);
}
TanStack Startでは、createFileRoute
関数内のローダー関数を使って、読み込み時に関数を実行できます。このコードでユーザーとその投稿を読み込み時に取得します。
import { prisma } from "../lib/prisma";
import { createServerFn } from "@tanstack/react-start";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({
component: Home,
loader: () => {
return getUsers();
},
});
const getUsers = createServerFn({ method: "GET" }).handler(async () => {
return prisma.user.findMany({
include: {
posts: true,
},
});
});
function Home() {
return (
<div>
<h1>Posts</h1>
</div>
);
}
Route.useLoaderData()
を使用して、ローダーからの応答をメインコンポーネントに保存します。
import { prisma } from "../lib/prisma";
import { createServerFn } from "@tanstack/react-start";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({
component: Home,
loader: () => {
return getUsers();
},
});
const getUsers = createServerFn({ method: "GET" }).handler(async () => {
return prisma.user.findMany({
include: {
posts: true,
},
});
});
function Home() {
const users = Route.useLoaderData();
return (
<div>
<h1>Posts</h1>
</div>
);
}
3.3 ユーザーと投稿を表示する
次に、ホームページを更新して、データベースから取得したユーザーと投稿を表示します。
users
をマッピングし、それらをposts
とともにリストで表示します。
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import prisma from "../../lib/prisma";
export const Route = createFileRoute("/")({
component: Home,
loader: () => {
return getUsers();
},
});
const getUsers = createServerFn({ method: "GET" }).handler(async () => {
return prisma.user.findMany({
include: {
posts: true,
},
});
});
function Home() {
const users = Route.useLoaderData();
return (
<div>
<h1>Posts</h1>
<ul>
{users.map((user) => (
<li key={user.id}>
{user.name}
<ul>
{user.posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</li>
))}
</ul>
</div>
);
}
この設定により、データベースから直接取得された投稿がページに表示されます。
次のステップ
Prisma ORMをTanStack Startと正常に統合し、シームレスなフルスタックアプリケーションを作成しました。次にできることのいくつか提案を以下に示します。
- より複雑なデータ関係を処理するためにPrismaモデルを拡張する。
- アプリケーションの機能を強化するために、追加のCRUD操作を実装する。
- PrismaとTanStack Startのさらなる機能を探索して、理解を深める。
- Prisma Postgresをチェックして、アプリケーションをスケーリングする方法を確認してください。
詳細情報
Prismaとつながる
以下を通じてPrismaの旅を続けましょう 私たちの活発なコミュニティ。情報を入手し、参加し、他の開発者と協力しましょう。
- Xでフォローする お知らせ、ライブイベント、役立つヒントのために。
- Discordに参加する 質問をしたり、コミュニティと話したり、会話を通じて積極的なサポートを受けたりできます。
- YouTubeを購読する チュートリアル、デモ、ストリームのために。
- GitHubで交流する リポジトリにスターを付けたり、問題を報告したり、問題に貢献したりしてください。