Prisma ORMとNext.jsの包括的な使用ガイド
Prisma ORMとNext.jsは、最新のサーバーサイドレンダリングおよびAPI駆動のWebアプリケーションを構築するための強力な組み合わせです。このガイドでは、それらの可能性を最大限に引き出すためのさまざまなヒントと戦略をまとめています。ベストプラクティス、モノレポのセットアップガイダンス、または動的な使用方法の戦略を探している場合でも、対応できます。
開発でのPrisma Clientの使用に関するベストプラクティス
複数のPrisma Clientインスタンスを避ける
Next.jsアプリケーションを開発する際、よくある問題の1つは、Prisma Clientの複数のインスタンスを誤って作成してしまうことです。これは、開発におけるNext.jsのホットリロード機能が原因でよく発生します。
これが起こる理由
Next.jsのホットリロード機能は、コードの変更を即座に反映するためにモジュールを頻繁にリロードします。ただし、これによりPrisma Clientの複数のインスタンスが作成され、リソースを消費し、予期しない動作を引き起こす可能性があります。
推奨される解決策
これを避けるために、グローバル変数を使用して単一のPrisma Clientインスタンスを作成します。
// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma =
globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
このアプローチを使用すると、開発中のホットリロード中でも、Prisma Clientのインスタンスが1つだけ存在することが保証されます。
モノレポでのPrisma ORMのセットアップ
モノレポでのPrisma ORMの使用の課題
モノレポを使用すると、複数のプロジェクトがコードと依存関係を共有できるため、最新の開発で人気のある選択肢となっています。ただし、モノレポでPrisma ORMを使用すると、依存関係の解決とスキーマ管理に関連する課題が発生する可能性があります。
主な問題
- 依存関係の解決:モノレポ内の複数のパッケージが異なるバージョンのPrisma ORMを使用している場合、競合が発生する可能性があります。
- スキーマの集中化:複数のプロジェクトにわたって単一のPrisma Schemaを管理することは複雑になる可能性があります。
モノレポ統合のベストプラクティス
-
Prisma Schemaを集中化する:一貫性を確保するために、`schema.prisma`ファイルを`@myorg/db`などの共有パッケージに配置します。
-
生成されたクライアントにカスタム出力ディレクトリを使用する:パッケージ間の一貫性を維持するために、生成されたPrisma Clientのカスタム出力ディレクトリを定義します。
-
ルートに依存関係をインストールする:バージョンの競合を防ぐために、モノレポのルートにPrisma ORMをインストールします。個々のパッケージがPrismaに直接アクセスする必要がある場合(例:ローカルクライアント生成の場合)、それらのパッケージ内にもインストールします。Turborepoのようなモノレポツールを使用し、そのベストプラクティスに従うか、同様の戦略を採用して、アプリ全体で依存関係を同期させることができます。
-
生成にNPMスクリプトを使用する:
{
"scripts": {
"prisma:generate": "prisma generate --schema=./packages/db/schema.prisma"
}
}
このアプローチにより、Prisma Schemaと生成されたクライアントがモノレポ内のすべてのプロジェクト間で同期されます。
Next.jsでのPrisma Clientの動的な使用
動的なシナリオの処理
テナント固有のデータベースを扱うなどの動的なユースケースでは、Next.jsでPrisma ORMを使用する際に、追加の考慮事項が必要です。
問題
各テナントは独自のデータベースを持っている可能性があり、実行時に個別のPrisma Clientを作成する必要があります。これは、Next.jsのハイブリッドレンダリングモデルのために複雑になる可能性があります。
解決策
テナント固有の構成に基づいてPrisma Clientを動的に作成するためにファクトリ関数を使用します。
// lib/prismaDynamic.ts
import { PrismaClient } from "@prisma/client";
type TenantConfig = {
databaseUrl: string;
};
export function createPrismaClient(config: TenantConfig): PrismaClient {
return new PrismaClient({
datasources: {
db: {
url: config.databaseUrl,
},
},
});
}
リソースの枯渇を避けるために、動的に作成されたPrisma Clientのライフサイクルを管理するようにしてください。