【Next.js】Drizzle ORMを導入してマイグレーションするまで
0. 前提
- Next.js 14(App Router)
- DBはVercel Postgresを利用する
1. プロジェクトを作成
npx create-next-app@latest
2. ライブラリをインストール
npm i drizzle-orm pg @vercel/postgres
npm i -D drizzle-kit eslint-plugin-drizzle @types/pg
3. drizzleの下準備
.eslintrc.json{
"extends": [
...
"plugin:drizzle/recommended"
]
}
tsconfig.json{
"compilerOptions": {
...
"target": "es5"
"target": "es6"
}
}
Drizzle Kitのコマンド実行のために、ECMAScriptのバージョンを切り替える。
4. DBの接続情報を追加
.env.localPOSTGRES_URL="postgres://aaa:bbb@ccc/ddd?sslmode=require"
利用するDBのURLを環境変数に設定する(今回はVercel Postgresを利用するので、管理画面から取得した)。
5. configファイルの実装
mkdir -p src/infra/db/schemas
mkdir -p src/infra/db/migrations
スキーマを設定するschemas
ディレクトリと、マイグレーションファイルを出力するmigrations
ディレクトリを作成する。
src/infra/db/drizzle.config.tsimport 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. スキーマの宣言
src/infra/db/schemas/user.tsimport {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に接続
src/infra/db/index.tsimport { 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. ファイルの作成
package.json{
"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.sql
CREATE 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:preview
Drizzle 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してみると、先程追加したレコードが取得できた。