🐕

Express+PrismaでAPIを作成してVercelにDeployする

2025/01/02に公開

はじめに

ExpressとPrismaを使用してAPIを作成してVercelにdeployする際に、個人的につまった箇所がいくつかあったので、備忘録的な感じでまとめてみます。
以下の記事、ならびにドキュメントを参照させていただきました。
https://zenn.dev/yamo/articles/prisma-express-rest-api
https://vercel.com/guides/using-express-with-vercel
ソースコードはこちらです。
https://github.com/kimshun0213kr/express-zenn

環境構築

基本的にはVercelのドキュメントの通り進めます。

プロジェクトの作成

$ mkdir vercel-express-project
$ cd vercel-express-project
$ npm init -y

express、vercelのインストール

$ npm install express vercel

セットアップと動作確認

アプリケーションのセットアップ

apiというディレクトリを作成し、その中にindex.tsを作成します。
作成したら、動作の確認のためにapi/index.tsを以下のように編集します。

api/index.ts
import express from "express";
const app = express();

app.use(express.json())
app.get("/", (req, res) => res.send("Express on Vercel"));

export default app;

tsconfig.jsonをルートディレクトリ内に作成し、以下のように設定します。

tsconfig.json
{
    "compilerOptions": {
      "outDir": "./dist",
      "rootDir": "./api",
      "target": "ES6",
      "module": "commonjs",
      "esModuleInterop": true
    },
    "include": ["api/**/*"]
}

vercelの設定

vercel.jsonを使用して、プロジェクトの設定を行います。
ここでは、以下のように設定を行いました。

vercel.json
{
  "version": 2,
  "installCommand": "npm install"
  "routes": [{ "src": "/(.*)", "dest": "/api/index.ts" }],
  "outputDirectory": "/dist"
}

vercel.jsonの編集が終了したら、以下のコマンドを実行してVercelにログインします。

$ vercel login

ローカル環境でのサーバーの起動

一度ローカル環境でサーバーを起動し、正常に動作するかを確認します。

$ vercel dev

初回起動時には、CLI上でプロジェクトに関する設定が求められますので、以下を参考に適宜設定を行ってください。

初回起動時の設定

☆で前後を囲ってある箇所は設定が各自で異なります。

Vercel CLI 34.2.1
? Set up and develop “~/vercel-express-project”? yes
? Which scope should contain your project? ☆USER's projects☆
? Link to existing project? ☆no☆
? What’s your project’s name? ☆vercel-express-project☆
? In which directory is your code located? ./
Local settings detected in vercel.json:
- Output Directory: /dist
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Development Command: None
? Want to modify these settings? no
🔗  Linked to USER/vercel-express-project (created .vercel and added it to .gitignore)
> Ready! Available at http://localhost:3000

正常に起動した状態でhttp://localhost:3000にアクセスすると以下のような画面になります。

この時点でのディレクトリ構成

.
├── api
│   └─── index.ts
├── node_modules
│   └─── 省略
├── package-lock.json
├── package.json
├── tsconfig.json
└── vercel.json

Prismaのインストール

Prismaの設定

無事に起動することが確認出来たら、Prismaの設定を行います。
以下のコマンドを実行し、Prismaの初期化を行います。

$ npx prisma init

このコマンドを実行することで、Prismaの初期化が行われ、.envとprismaというディレクトリの中にschema.prismaというファイルが生成されます。
これらを以下のように編集します

.env
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQL Server and SQLite.
# 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"
+ DATABASE_URL="postgresql://postgres:password@localhost:5433/mydb"

DATABASE_URLは、適宜自分が使用しているデータベースへのURLに変更します。

prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

+ model User {
+   id    Int @id @default(autoincrement())
+   name  String
+   email String
+ }

今回のスキーマは、ユーザーのidnameemailを格納できるように設定しています。
これらの設定が終了したら、以下のコマンドを実行して、データベースときちんと接続されているかを確認します。

$ npx prisma db push

このコマンドが正しく終了すれば、エラーが無く、正しく接続ができているという事になります。

データの追加

では、データベース上にデータを追加してみましょう。
以下のコマンドを実行し、prisma studioを起動します。

$ npx prisma studio

このコマンドを実行すると、http://localhost:5555上でデータベースの操作が行えるようになります。
今回はこのように追加してみました。

APIの作成

API本体の作成

ではいよいよAPIの作成に移ります。
apiディレクトリ内にuserControllerディレクトリを作成し、その中にuserController.tsを作成します。
作成出来たら、まずは以下のように編集します。

api/userController/userController.ts
import { PrismaClient } from "@prisma/client";
import { Router, Request, Response } from "express";

const prisma = new PrismaClient();
const router = Router();

router.get("/", async (req: Request, res: Response) => {
  const users = await prisma.user.findMany();
  res.json({ users });
});

export default router;

findMany()は、条件に合ったデータを全件返します。
ここでは条件を何も指定していないため、すべてのデータが取得されます。
Prismaのチートシートに色々なコマンドが載っているので詳しくはそちらをご覧ください。
https://qiita.com/koffee0522/items/92be1826f1a150bfe62e
このように編集ができたら、api/index.tsを以下のように編集します。

api/index.ts
import express from "express"
+ import userController from "./userController/userController"
const app = express();

app.use(express.json())
app.get("/", (req, res) => res.send("Express on Vercel"));
+ app.use("/user",userController);

export default app;

app.use("/user",userController);と記述することで、/user以下のリクエストは全てuserController側で行われるようになります。

現在のディレクトリ構成

.
├── api
│   ├─── userController
│   │   └───userController.ts
│   └─── index.ts
├── node_modules
│   └─── 省略
├── package-lock.json
├── package.json
├── tsconfig.json
└── vercel.json

app.use()を使用せずにAPIを作成する方法

app.use()を使用せずに作成するには、app.get()で記述します。
例えば、app.use()を使用せずにapi/index.tsを編集すると、以下のようになります。

api/index.ts
import express from "express"
- import userController from "./userController/userController"
+ import { PrismaClient } from "@prisma/client";

+ const prisma = new PrismaClient();
const app = express();

app.use(express.json())
app.get("/", (req, res) => res.send("Express on Vercel"));
- app.use("/user",userController);
+ app.get("/user",async(req,res) => {
+     const user = await prisma.user.findMany();
+     res.json({user})
+ }

export default app;

このような記述で実装ができますが、これ以降複数のAPIエンドポイントを作成するとなると、見にくくなってしまいますので、適宜別ファイルにコントローラーを作成します。

起動確認

編集が完了したら、再度vercel devコマンドでサーバーを起動します。
サーバー起動後、http://localhost:3000/userにアクセスしてみましょう。
アクセスすると、以下のようにデータがjson方式で取得できていることが分かります。

Vercelへのデプロイ

このままVercelにデプロイを行うと、TypeScriptからJavaScriptへのコンパイルやprisma generateが行われず、正しくアプリケーションが機能しないため、vercel.jsonを以下のように編集します。

vercel.json
{
  "version": 2,
  "installCommand": "npm install"
+ "buildCommand": "tsc && npx prisma generate",
  "routes": [{ "src": "/(.*)", "dest": "/api/index.ts" }],
  "outputDirectory": "/dist"
}

このようにbuildCommandtsc && npx prisma generateを指定することで、正しく機能します。
そして、デプロイを行う前に、.envに記載されているDATABASE_URLをVercelにアップロードする必要があります。
Vercelのプロジェクトのページに行き、Settings > Environment Variablesから登録を行います。

登録が完了したら、以下のコマンドを実行し、プレビュー状態でのデプロイを行います。

$ vercel

このコマンドが正しく実行出来たら、以下のように表示されます。

この表示が出たら、Preview: 以下のURLにアクセスし、正しくAPIが機能していることを確認します。
正しく機能していることが確認出来たら、以下のコマンドで本番環境へのdeployが可能です。

$ vercel --prod

終わりに

今回はexpressとprismaを使用してAPIを作成し、Vercelにデプロイしてみました。
expressはほぼ初めて触ったのですが、今後も使ってみようと思います。

Discussion