【Next.js】Drizzle ORMを導入してマイグレーションするまで
0. 前提
- Next.js 14(App Router)
- DBはVercel Postgresを利用する
1. プロジェクトを作成
npx create-next-app@latest2. ライブラリをインストール
npm i drizzle-orm pg @vercel/postgresnpm i -D drizzle-kit eslint-plugin-drizzle @types/pg3. drizzleの下準備
{ "extends": [ ... "plugin:drizzle/recommended" ]}{ "compilerOptions": { ... "target": "es5" "target": "es6" }}Drizzle Kitのコマンド実行のために、ECMAScriptのバージョンを切り替える。
4. DBの接続情報を追加
POSTGRES_URL="postgres://aaa:bbb@ccc/ddd?sslmode=require"利用するDBのURLを環境変数に設定する(今回はVercel Postgresを利用するので、管理画面から取得した)。
5. configファイルの実装
mkdir -p src/infra/db/schemasmkdir -p src/infra/db/migrationsスキーマを設定するschemasディレクトリと、マイグレーションファイルを出力するmigrationsディレクトリを作成する。
import type { Config } from 'drizzle-kit';import { cwd } from 'node:process';import { loadEnvConfig } from '@next/env';
loadEnvConfig(cwd());
export default { schema: './src/infra/db/schemas/*', out: './src/infra/db/migrations', driver: 'pg', dbCredentials: { connectionString: process.env.POSTGRES_URL ?? '', },} satisfies Config;各種設定のためのdrizzle.config.tsを作成し、先ほどのディレクトリ達を指定する。
またDrizzle Kitコマンド実行時にも環境変数を参照したいので、loadEnvConfigを呼び出しておく。
6. スキーマの宣言
import {pgTable, text, uuid} from 'drizzle-orm/pg-core';
export const userSchema = pgTable('users', { id: uuid('id').defaultRandom().notNull().primaryKey(), name: text('name').notNull(), email: text('email').notNull(),});今回はサンプルとして簡易なusersテーブルを作成する。
7. DBに接続
import { drizzle } from 'drizzle-orm/vercel-postgres';import { VercelPool } from '@vercel/postgres';import drizzleConfig from '@/infra/db/drizzle.config';
const connection = new VercelPool(drizzleConfig.dbCredentials);export const db = drizzle(connection);8. マイグレーション
8-1. ファイルの作成
{ "scripts": { "db:generate": "drizzle-kit generate:pg --config ./src/infra/db/drizzle.config.ts", "db:push": "drizzle-kit push:pg --config ./src/infra/db/drizzle.config.ts", "db:preview": "drizzle-kit studio --config ./src/infra/db/drizzle.config.ts" }}Drizzle Kitのコマンドをnpm scriptsに設定しておく。今回はconfigファイルをルートに作成していないので、オプションで明示的にパスを指定する。
npm run db:generate叩く。
└── db ├── schemas └── migrations └── meta └── 0000_snapshot.json └── _journal.json └── 0000_lovely_iron_man.sqlCREATE TABLE IF NOT EXISTS "users" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "name" text NOT NULL, "email" text NOT NULL);するとmigrations下に、宣言したスキーマにマイグレートするためのSQLファイルが作成されている。
8-2. 実行
npm run db:pushこれでDBにスキーマの変更が反映された。
9. CRUDを試す
npm run db:previewDrizzle Studioを起動し、usersテーブルに適当なレコードを追加する。
import { db } from '@/infra/db';import { userSchema } from '@/infra/db/schemas/user';
export default async function Home(): Promise<JSX.Element> { const users = await db.select().from(userSchema); // => [ // { // id: '451a3667-8f34-4796-9b24-6cdfeade0877', // name: 'user', // email: 'test@example.com', // } // ]
return <>...</>;}任意のコンポーネント内でdrizzleのクエリを用いてusersをSELECTしてみると、先程追加したレコードが取得できた。
参考