[ハンズオン] Next.js x DrizzleORM x Docker Todoアプリ ~①環境構築編~

Next.js

公開日時:2024/05/25

環境構築編とコーディング編に分けて記事を作成します。

今回は環境構築編です。

主な技術スタック


  • Next.js 14 (フロントとサーバサイド)
  • DrizzleORM (DB操作)
  • drizzle-zod (バリデーション・スキーマ作成)
  • Docker (postgresql15 ローカルでdbを構築)
  • Tailwind CSS (cssフレームワーク)
  • shadcn/ui (UIライブラリ)
  • tempo (日付ライブラリ)
  • bun (JavaScriptランタイム 適宜npmなどに読み替えてください)

1. プロジェクト作成


  • bun create next-app
  • 設定が聞かれるが全てyesで良い。(適宜変更する)
  • プロジェクトが作成されるのでcdコマンドで移動する

2-1. 環境構築(パッケージインストール)


※ここからはカレントディレクトリがプロジェクト直下前提になります。

  • bun run dev でローカル環境が起動するか確認(省略可)
  • 使用するパッケージをインストールしていく

DrizzleORM・drizzle-zod

ドキュメント

drizzle-orm,postgres.js,drizzle-kit,drizzle-zodをインストールする。

bun add drizzle-orm postgres
bun add -D drizzle-kit
bun add drizzle-zod

shadcn/ui

ドキュメント

uiライブラリのshadcn/uiをインストールする。
このライブラリは必要なコンポーネントは別でインストールするため、ここでは設定のみ。
オプションが聞かれるが、テーマの設定に関するものなのでデフォルトのままで良い。
components.jsonが作成される。

bunx shadcn-ui@latest init

tempo

ドキュメント

日付ライブラリ。day.jsなどが有名だが最近人気のあるtempoを試しで採用。使用感は非常に良い。ドキュメントも見やすい。

bun install @formkit/tempo

2-2. 環境構築(Docker)


dockerの詳細については説明はしない。あくまでローカル環境にdbを構築するためだけに使用する。

  • docker-compose.ymlを作成する。
    • image: postgres:15
    • port: 5432 (postgresのデフォルト)
    • environment: おまかせ。ここで設定したものがDATABASE_URLとして使われる。
      docker-compose.yml
      version: '3.9'
      
      services:
        db:
          image: postgres:15
          ports:
            - '5432:5432'
          environment:
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: postgres
            POSTGRES_DB: postgres
          volumes:
            - ./data:/var/lib/postgresql/data
      
  • docker compose up -d を実行するとdockerコンテナが起動する。imageがない場合はimageを取得するところから始まるので時間がかかる。
  • Docker-Desktop などでコンテナが起動しているか確認する。
  • 今後起動と停止については登場しないので適宜行なってください。

3. DrizzleORM 初期設定


  • .env.localファイルを作成する
    • DATABASE_URLを環境変数として管理する。
    • ※docker-compose.ymlの設定値で変わるので注意
      .env.local
      DATABASE_URL='postgres://postgres:postgres@localhost:5432/postgres'
  • drizzle.config.tsを作成する
    • デフォルトでこの名前のファイルを使う設定になっているので、名前は変えないことを推奨
    • dialect: postgresqlを設定
    • schema: スキーマの定義ファイルのパスを指定
    • out: マイグレーションファイルなどを吐き出すディレクトリを指定
    • dbCredentials: dbのurlを設定。今回は環境変数に設定したURLをそのまま使う
      drizzle.config.ts
      import { defineConfig } from 'drizzle-kit';
      export default defineConfig({
        dialect: 'postgresql',
        schema: './src/db/schema.ts',
        out: './drizzle',
        dbCredentials: {
          url: process.env.DATABASE_URL || '',
        },
      });

4. コマンドをscriptに登録する


package.jsonのscriptにコマンドを追加する。
以下のコマンドを追加

  • db:generate : マイグレーションファイルを生成
  • db:push : マイグレーションファイルをdbに適用する
  • db:studio : dbのGUIツールを起動する
package.json
    "db:generate": "drizzle-kit generate",
    "db:push": "drizzle-kit push",
    "db:studio": "drizzle-kit studio"

5. スキーマを定義する


src/db/schema.tsを作成しスキーマを定義していく。

  • id: ユニークな識別子。serialにすることでauto-incrementされる。
  • title: タスクのタイトル。
  • status: 'notStarted', 'imProgress', 'completed' の3つのenum型にする。 デフォルト(新規作成時)で 'notStarted'になる。
  • createdAt: 作成時間
  • updatedAt: 更新時間
src/db/schema.ts
import { pgEnum, pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';

export const statusEnum = pgEnum('status', [
  'notStarted',
  'imProgress',
  'completed',
]);

export const todo = pgTable('todo', {
  id: serial('id').primaryKey().notNull(),
  title: text('title').notNull(),
  status: statusEnum('status').default('notStarted').notNull(),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at')
    .defaultNow()
    .notNull()
    .$onUpdate(() => new Date()),
});

6. db確認


スキーマ定義まで完了するとdbの確認ができるようになる。

以下のコマンドを実行し、drizzle-studioが起動することを確認する。

bun run db:generate
bun run db:push
bun run db:studio

問題なければdrizzle-studio上でデータの操作ができるようになっているはず。
Add recordをクリックして作成できるか確認する。

以上で環境構築は終了になります。次回は実際にコーディングしてCRUD機能を一通り作成していきます。