Next.js(App Router) x PlanetScale x Prisma でプロジェクトを構築
はじめに
- Next.js(App Router)、PlanetScale、Prisima でプロジェクトを構築する方法を紹介します。
- PlanetScale でアカウントを作成し、実際にデータベースを作成します。
- Prisma を通して、テーブルを作成、データを投入します。
- Next.js の App Router を使って、データベースのデータを取得、表示します。
- 本記事で作成したソースコードは以下にあります。
PlanetScaleについて
PlanetScale とは、クラウドネイティブな MySQL データベースです。シームレスなスケーリング、高可用性、セキュリティを備えています。裏側としては、Vitessというオープンソースのデータベースが採用されています。
PlanetScale の特出すべき特徴は以下の2点です。
- MySQL を利用したサーバレスな DB
- ブランチ機能によるデータベースのバージョン管理
特にブランチ機能は PlanetScale ならではの強みで、商用 DB から、開発 DB を作成できます。開発 DB でのテストが終わったら、ブランチをマージすることで、本番 DB に反映させることができます。本記事でも取り上げています。
Prismaについて
Prisma は Node.js と TypeScript 用のオープンソース ORM です。ORM とは、SQL を書かずに、データベースを操作するためのライブラリです。
Prisma は、型安全なデータベースアクセスが特徴です。TypeScript との相性が良いです。
Prisma は以下の 3 つのモジュールを提供します。
- Prisma Client
- プログラムからデータベースを操作するためのクライアントライブラリ
- Prisma Migrate
- データベースのマイグレーションを実現するためのツール
- Prisma Studio
- データベースをそうさするための GUI ツール
以下のようなデータベースをサポートしています。
- PostgreSQL
- MySQL
- SQLite
- MongoDB
- etc...
それでは、実際のプロジェクトを作成しながら、PlanetScale と Prisma の使い方を紹介していきます。
新規にNext.js プロジェクトを作成
プロジェクトを新規に作成します。今回は、next-app@latest
を利用し、最新のバージョンをりようします。また、App Router を利用するため、--app
を指定しています。
$ pnpm create next-app@latest nextjs-planetscale-prisma --typescript --eslint --import-alias "@/*" --src-dir --use-pnpm --tailwind --app
プロジェクトに移動します。
$ cd nextjs-planetscale-prisma
環境変数ファイルを作成
.env
の空ファイルを作成します。これは後ほど利用します。
$ touch .env
.gitignoreを修正
以下を追加し、.env
を Git の管理対象から外します。
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
+.env
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
Prismaをインストール
Prisma CLI を devDependencies としてインストールします。
$ pnpm add -D prisma
Prismaの設定ファイルを作成
Prisma を Prisma CLI の init コマンドで初期化します。
$ npx prisma init
✔ Your Prisma schema was created at prisma/schema.prisma
You can now open it in your favorite editor.
warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.
Next steps:
1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver, mongodb or cockroachdb.
3. Run prisma db pull to turn your database schema into a Prisma schema.
4. Run prisma generate to generate the Prisma Client. You can then start querying your database.
More information in our documentation:
https://pris.ly/d/getting-started
✔ あなたのPrismaスキーマはprisma/schema.prismaで作成されました。
お気に入りのエディタでそれを開くことができます。
注意 すでに.gitignoreファイルが存在します。.envを追加して、プライベートな情報をコミットしないようにしてください。
次のステップ:
1. 環境変数のDATABASE_URLを.envファイル二設定してください。DATABASE_URLは既存のデータベースへの接続情報です。まだテーブルが存在しない場合は、https://pris.ly/d/getting-started を読んでください。
2. 「schema.prisma」ファイルの「datasource」ブロックにあるプロバイダをあたなのデータベースにあわせて設定してください。(例:postgresql、mysql、sqlite、sqlserver、mongodb、またはcockroachdb)
3. 「prisma db pull」コマンドを実行し、データベーススキーマをPrismaスキーマに変換してください。
4. 「prisma generate」コマンドを実行し、Prismaクライアントを生成してください。その後、データベースへのクエリを開始できます。
詳細な情報は、以下のドキュメントを参照してください:
https://pris.ly/d/getting-started
実行後にファイルが2つ生成されます。
- 1つ目が Prisma の設定ファイル(
prisma/schema.prisma
)です。 - 2つ目が
.env
ファイルです。.env
ファイルが無ければ新規に作成されます。.env
ファイルにはデータベースへの接続情報を後ほど記入します。
自動生成された Prisma の設定ファイル(prisma/schema.prisma
)です。
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
自動生成された、.env
ファイルです。
# This was inserted by `prisma init`:
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
それでは、つづいて、PlanetScale の設定します。
PlanetScaleのアカウントを作成
PlanetScale のアカウントを作成します。アカウントは手持ちの GitHub アカウントで簡単に作成できます。
サイトにアクセスします。
「Get started」をクリックします。
「Continue with GitHub」をクリックします。
自身が持っている GitHub アカウントでログインします。
「Authorize planetscale」をクリックします。
「Accept Terms of Service」をクリックします。
この画面に到達すると、自身のメールアドレスに確認メールが届いていますので、メールボックスを確認します。
「Confirm email」をクリックし、アカウント作成を完了させます。
アカウント作成が完了しました。
PlanetScaleでデータベースを作成
続いて、データベースを作成していきます。
初めにチュートリアルが表示されるので、ボタンをクリックして次へ進めていきます。
これでチュートリアル完了です。「Create your first database」をクリックして、データベースを作成します。
-
Name
にはデータベース名を記入します。 -
Region
はap-northeast-1(Tokyo)
を選択します。これで、日本リージョンにデータベースを作成できます。 - 最後に、「Create database」をクリックします。
「Initializing」と表示されているので、しばらく待ちます。
初期化が完了しました。
PlanetScaleでデータベースの接続先を取得
作成したデータベースへの接続先の情報を取得し、.env
に設定します。
「Get connection strings」をクリックします。
「Craete password」をクリックします。
- 接続先の情報が表示されました。
- 「Connection with」から「Prisma」を選択肢、Prisma の設定を表示できます。
- 「.env」に記入する環境変数が表示されています。環境変数に「DATABASE_URL」をコピーします。
Next.js の環境変数ファイルにペーストします。
DATABASE_URL='mysql://hfgoc4ilkyvziou170iu:pscale_pw_x6gHc5eEPDOCnCHgWCR9tglpAMpLNMQLbL2Mwv9OlO6@aws.connect.psdb.cloud/nextjs-planetscale-prisma?sslaccept=strict'
環境変数としてデータベースへの接続先情報を設定しました。
PlanetScaleでPrismaの設定を取得
ブラウザに戻り「schema.prisma」を表示させます。
ここには、Prisma の設定が記述されています。こちらも後ほど必要になります。
Next.js のプロジェクトの Prisma の設定ファイル(schema.prisma
)にペーストします。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
Prisma の設定を反映できました。
Prisma Clientをインストールします。
Prisma Client をインストールします。
$ pnpm add @prisma/client
prisma.schemaを編集します。
以下の Prisma のクイックスタートを参考にスキーマを修正します。
今回は、User テーブル、Post テーブルを定義します。
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+
+ @@index([authorId])
+}
DBにテーブルを作成する
スキーマ定義が完了したら、prisma db push
コマンドを実行し、PlanetScale の DB にテーブルを作成します。User テーブル、Post テーブルが作成されます。
$ npx prisma db push
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "nextjs-planetscale-prisma" at "aws.connect.psdb.cloud"
🚀 Your database is now in sync with your Prisma schema. Done in 528ms
✔ Generated Prisma Client (4.15.0 | library) to ./node_modules/.pnpm/@prisma+client@4.15.0_prisma@4.15.0/node_modules/@prisma/client in 72ms
PlanetScale のコンソールに戻り、テーブルが作成されていることを確認します。
Table の数が 0 から 2 に変更されています。「Tables」をクリックします。
するとテーブルの一覧が確認できました。テーブルの定義も確認できます。
Post
と User
の2つのテーブルが作成されていることが確認できました。
Prisma Studioでデータを作成
Prisma Studio を利用して、データを作成します。Prisma Studio とは、Prisma の GUI ツールです。
以下のコマンドを実行すると、ブラウザが起動し、http://localhost:5555/ で Prisma Studio が表示されます。
$ npx prisma studio
「User」をクリックし、User テーブルのレコードを確認します。
現状は空のため何も表示されません。「Add record」を追加し、データを作成します。
2 件レコードを入力しました。「Save 2 changes」をクリックし、データを保存します。
登録が完了しました。id
は prisma.schema
で autoincrement()
を設定しているため、自動的にインクリメントされた値が登録されていきます。
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
続いて、Post テーブルにもデータを登録します。「Add record」を追加します。
データを入力します。先程作成した User と関連付けるため、「User」をクリックします。
関連付けたい User を選択します。
「Save 1 change」をクリックして、データを登録します。
データの登録が完了しました。
以上で、PrismaStudio を利用したデータの登録は完了です。
PlanetScaleでデータを確認する
先程登録したデータが PlanetScale のコンソールで確認できることを確認します。
「Console」をクリックします。
「Connect」をクリックします。
エディターが表示されるので SQL を入力します。
SQL | 説明 |
---|---|
select * from User |
Userテーブルのすべてのデータを表示します。 |
select * from Post |
Postテーブルのすべてのデータを表示します。 |
データが表示されました。
Next.jsでデータを取得
Next.js から Prisma に接続するためのクライアントを prismaClient.ts
に作成します。
$ mkdir -p src/lib
$ touch src/lib/prismaClient.ts
import { PrismaClient } from '@prisma/client';
export * from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const prisma =
globalForPrisma.prisma ||
new PrismaClient({
log:
process.env.NODE_ENV === 'development'
? ['query', 'error', 'warn']
: ['error'],
});
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
データベースに接続し、User
と Post
のデータを取得し結果を表示するページを作成します。処理はサーバサイドで実行されます。注目すべきポイントはコメントとして記述しています。
$ mkdir -p src/app/select
$ touch src/app/select/page.tsx
// データベースに接続するためのクライアントをインポート
import { prisma } from "@/lib/prismaClient";
export default async function Home() {
// Userテーブルから全てデータを取得
const users = prisma.user.findMany();
// Postテーブルから全てデータを取得
const posts = prisma.post.findMany();
return (
<>
<h1 className="font-bold text-2xl">Users</h1>
{/* Userテーブルの結果の一覧を画面に出力する */}
{(await users).map((user, index) => (
<div key={user.id} className="bg-gray-800 m-2 w-[300px]">
<p>id: {user.id}</p>
<p>name: {user.name}</p>
<p>email: {user.email}</p>
{/* Add more user attributes as needed */}
</div>
))}
<br/>
<h1 className="font-bold text-2xl">Post</h1>
{/* Postテーブルの結果の一覧を画面に出力する */}
{(await posts).map((post, index) => (
<div key={post.id} className="bg-gray-800 m-2 w-[300px]">
<p>id: {post.id}</p>
<p>name: {post.title}</p>
<p>content: {post.content}</p>
<p>published: {post.published+``}</p>
<p>authorId: {post.authorId}</p>
</div>
))}
</>
);
}
今回は findMany
を利用していますが、Prisma では様々な API が用意されています。詳細は以下のリンクを参照してください。
実行します。
$ pnpm dev
http://localhost:3000/select にアクセスすると、以下のようにデータが表示されます。
PlanetScaleでデータを手動でバックアップする
PlanetScale ではデータベースのデータをバックアップできます。バックアップは手動で行うこともできますが、定期的に自動でバックアップを行うこともできます。バックアップについては公式サイトに記載されています。
まず、手動バックアップの方法です。
「Backups」にアクセスし、「Create new backup」をクリックします。
- 「Branch」を指定します。
- 「Name」は適当に入力します。
- どの程度の期間バックアップを保持するかを指定します。
- 「Create backup」をクリックします。
バックアップの作成が完了しました。バックアップの作成には数分かかります。
PlanetScaleでデータを定期的にバックアップする
スケジュールを登録し、定期的にバックアップをする設定をします。
「Backups」にアクセスし、「Add new schedule」をクリックします。
- 実行する頻度、タイミングを指定します。(今回は毎日、10:47 に実行するように設定しています)
- どの程度の期間バックアップを保持するかを指定します。(今回は、1 ヶ月間保存するように設定しています。)
- 任意で名前を指定します。
- 最後に、「Save schedule」をクリックします。
デイリーでバックアップが作成されるように設定されました。
PlanetScale でデータを定期的にバックアップする設定は以上です。
PlanetScaleでモニタリング
Insight でクエリの実行結果のログとパフォーマンスを可視化できます。以下の公式サイトで記述されています。
Insights のページを開きます。
グラフエリアでは、以下の種類のグラフを選択できます。
グラフ | 説明 |
---|---|
Query latency | クエリの実行時間 |
Queries per second | 秒間のクエリ数 |
Rows read per second | 秒間の読み込み行数 |
Rows written per second | 秒間の書き込み行数 |
Query errors | クエリのエラー数 |
実行されたクエリの一覧を確認できます。エラーのクエリに絞って見ることもできます。
PlanetScaleで開発ブラントを作成する
PlanetScale では目的にあわせて、DB をブランチとして管理できます。ブランチについては以下の公式サイトで記述されています。
まず、開発用ブランチを作成します。「New branch」をクリックします。
- 「Name」にブランチ名を記載します。
- 「Create branch」をクリックしてブランチを作成します
「dev」ブランチが作成できました。
PlanetScaleで商用ブラントを作成する
次に、「main」ブランチを商用ブランチにプロモートします。「main」をクリックします。
「Promote to production」をクリックして、商用ブランチにプロモートします。
商用ブランチにプロモートできました。
ブランチの全体像です。
- main が商用ブランチです。
- dev が開発ブランチです。
まとめ
- Next.js(App Router)、PlanetScale、Prisima でプロジェクトを構築する方法を紹介しました。
- PlanetScale でアカウントを作成し、実際にデータベースを作成しました。
- Prisma を通して、テーブルを作成、データ投入しました。
- Next.js の App Router を使って、データベースのデータを取得、表示しました。
Prisma もいいですが、最近話題の Drizzle を今度は使ってみたいです。
Discussion