2章 Dockerで構築したNext.js、Nest.js、MySQL、Prismaで疎通確認を行う。
前回の記事で構築した環境で、フロントエンド、バックエンド、データベースでの最小構成による疎通確認を行う。
前回の記事
コピペに頼らない。ちゃんと理解するDocker(docker-compose)構築:Next.jsとNest.jsの環境構築
https://zenn.dev/delta_tsuruta/articles/6b0eb34f5e3805
ここまでくれば、あとは皆さん各々でプロジェクトを進めることが出来ると思っている。
前提条件
docker compose upで次の環境、ポートが起動していること
- frontend ポート 3000
- backend ポート 3001
- db ポート 3306
上記はdocker compose psで確認が可能。
ポートは適宜変更してもってもOK
今回は最小構成で作成するため、TypeScriptのORMであるPrisma以外は、特にパッケージのインストールは行わない。
フロントエンドとバックエンドの疎通
バックエンドの修正
必要なことは2つ。
- CORSの設定
- ポートの変更
CORSの設定
CORSの設定においては、今回最小構成のため厳密な設定は行わない。
Nest.jsの公式ドキュメント:CORS
https://docs.nestjs.com/security/cors
CORSとは
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
ポートの変更
フロントエンドでポート3000を使用しているため、Nest.jsのmain.tsで受付けるポートを変更する。
変更点
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
- await app.listen(process.env.PORT ?? 3000);
+ app.enableCors();
+ await app.listen(process.env.PORT ?? 3001);
}
bootstrap();
フロントエンドの修正
テストボタンの作成
'use client';
import Image from "next/image";
import React from "react";
export default function TestButton() {
const [buttonText, setButtonText] = React.useState("TEST BUTTON");
const fetchText = async () => {
const response = await fetch("http://localhost:3001");
const test = await response.text();
setButtonText(test);
};
const onClick = () => {
fetchText();
};
return (
<>
<button
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
onClick={onClick}
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
{buttonText}
</button>
</>
);
}
テストボタンの配置
+ import TestButton from "./testButton";
<div className="flex gap-4 items-center flex-col sm:flex-row">
- <a
- className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
- href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
- target="_blank"
- rel="noopener noreferrer"
- >
- <Image
- className="dark:invert"
- src="/vercel.svg"
- alt="Vercel logomark"
- width={20}
- height={20}
- />
- Deploy now
- </a>
- <a
- className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
- href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
- target="_blank"
- rel="noopener noreferrer"
- >
- Read our docs
- </a>
+ <TestButton>
</div>
これで次のような画面になる。
ボタンを押すとボタンのテキストがバックエンドからのレスポンスの文字列に変更される。
Prismaの導入
@prisma/clientとprismaをpackage.jsonに追加して、dockerを再度ビルドする。
"dependencies": {
"@nestjs/common": "^11.0.1",
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1",
+ "@prisma/client": "^6.3.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.18.0",
"@nestjs/cli": "^11.0.0",
"@nestjs/schematics": "^11.0.0",
"@nestjs/testing": "^11.0.1",
"@swc/cli": "^0.6.0",
"@swc/core": "^1.10.7",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.10.7",
"@types/supertest": "^6.0.2",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.2",
"globals": "^15.14.0",
+ "prisma": "^6.3.0",
"jest": "^29.7.0",
docker compose up --build
キャッシュによりパッケージがインストールされない場合はキャッシュを使わずにビルドする
docker compose build --no-cache && docker compose up
@prisma/clientとprismaがnode_modulesにインストールされたら、次のコマンドを実行してPrismaを初期化する。
$ npx prisma init
すると、プロジェクトのルートディレクトリに.envファイルとprisma/schema.prismaが作成される。
project
├ .env // 設定ファイル
├ prisma
│ └ schema.prisma // スキーマファイル
├ ...
...
今回はMySQLを使用するため、schema.prismaを次のように編集する。
generator client {
provider = "prisma-client-js"
}
datasource db {
- provider = "postgresql"
+ provider = "mysql"
url = env("DATABASE_URL")
}
urlのenv("DATABASE_URL")は、環境変数。
DATABASE_URLは次の構造で記述する。
DB_URL="mysql://root:password@localhost:3306/database_name"
DB_URL=データベース://ユーザ名:パスワード@パス:ポート/データベース名
今回はPrismaが作成してくれた.envファイルに次の設定を記述する。
DB_CONNECTION="mysql"
DB_USERNAME="root"
DB_PASSWORD="password"
DB_HOST="db"
DB_PORT="3306"
DB_DATABASE="database_name"
DATABASE_URL="${DB_CONNECTION}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}"
テーブルの作成
Prismaは、schema.prismaにテーブル定義を記述して、コマンドを実行することでCREATE TABLEが実行される仕組み。
今回は、次の通りusersテーブルを作成する。
テーブル名を指定したいので、@@map("users")を記述している
テーブル名の明示的な記述が無ければ、model Userと記述した場合は"User"という名前のテーブルが作成される。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
+model User {
+ id Int @default(autoincrement()) @id
+ email String @uniqu
+ name String?
+ @@map("users")
+}
データベースへの反映は次のコマンドを実行する。
# npx prisma migrate dev --name ファイル名
npx prisma migrate dev --name create_user_table
コマンドを実行することでmigrations配下に指定した名前のディレクトリ/ファイルが作成され、DBへ反映される。
migrations
├ 20250226000000_create_user_table
│ └ migration.sql
念のため、DBを確認しておくとよい
# dbのコンテナのbashを起動
docker compose exec db bash
# mysqlのCLIを起動
mysql -u root -ppassword
# データベース一覧を確認
SHOW DATABASES;
# テーブル一覧を確認
SHOW TABLES FROM テーブル名;
schema.prismaを変更した差分が一つのディレクトリとして作成される。
なお、ここまで完了すればDBの接続情報も正しく、バックエンドがDBと接続できていることは分かる。
これでフロントエンド-バックエンド-DBの疎通は確認が取れている状態となる。
ついでに、次回は簡単なCreateとGetがフロントエンドから行えるようにする。
by 株式会社DELTA
[CTO Booster]
[VersionUp booster]
Discussion