💻

Hono + Prisma + Cloudflare D1/R2をローカルだけで動かしてみる

2024/08/18に公開

概要

タイトル通りですが、Hono + Prisma + CloudflareのD1/R2のローカル環境をセットアップして、デプロイはせずにローカルだけで動かしてみて、挙動の確認などを試してみたいと思います。

👇以下軽く各サービスの概要説明になります。

Hono とは

https://hono.dev/

Edgesのための小さくシンプルで超高速なWebフレームワークです。どのJavaScriptランタイムでも動作します:Cloudflare Workers、Fastly Compute、Deno、Bun、Vercel、Netlify、AWS Lambda、Lambda@Edge、Node.js

Prisma とは

https://www.prisma.io/

Prismaは、Node.jsとTypeScriptのための次世代のORM (Object-Relational Mapping) です。データベースとのやり取りをより簡単かつ安全にするために設計されています。開発者がデータベーススキーマを定義し、そのスキーマに基づいて自動的に型安全なクライアントAPIを生成します。これにより、SQLやデータベース固有のクエリ言語に依存することなく、データベースとのやり取りが可能になります。

Cloudflare D1 とは

https://www.cloudflare.com/ja-jp/developer-platform/d1/

Cloudflare D1は、Cloudflareが提供する分散型SQLデータベースサービスです。D1は、データベースのパフォーマンスとスケーラビリティを向上させ、グローバルに分散されたデータベースを簡単に構築・管理できます。サーバーレスアーキテクチャに基づいており、高速なクエリ応答と高い可用性を実現します。これにより、開発者は複雑なインフラ管理を不要にし、アプリケーションの迅速な開発とデプロイを可能にします。

Cloudflare R2 とは

https://www.cloudflare.com/ja-jp/developer-platform/r2/

Cloudflare R2は、データ転送費用をなくしたオブジェクトストレージサービスです。Amazon S3と互換性があり、移行が容易です。大規模なデータ保存を低コストで提供し、既存のS3ツールやアプリともシームレスに統合できます。

環境構築

今回も👇の環境をcloneして構築していきます。(※ nodeが動く環境なら好きな環境で試してもらえればと思います)

https://github.com/Slowhand0309/nodejs-devcontainer-boilerplate

次に👇のファイルを少し修正してます。

  • .devcontainer/Dockerfile
FROM node:20.10.0-bullseye-slim
LABEL maintainer="Slowhand0309"

ARG username=vscode
ARG useruid=1000
ARG usergid=${useruid}

RUN set -ex \
    && apt-get update \
    && apt-get install -y \
        sudo \
        ca-certificates \ # ← 追加
        --no-install-recommends \
    # Delete node user with uid=1000 and create vscode user with uid=1000
    && userdel -r node \
    && groupadd --gid ${usergid} ${username} \
    && useradd -s /bin/bash --uid ${useruid} --gid ${usergid} -m ${username} \
    && echo ${username} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${username} \
    && chmod 0440 /etc/sudoers.d/${username}

USER ${username}
  • .devcontainer/compose.yaml
services:
  app:
    ...
    ports:
      - "8787:8787" # ← 追加

ここまできたらコンテナ起動し、コンテナ内で👇コマンドからhono + Cloudflare workers の環境をセットアップしていきます。

$ yarn create hono .
✔ Using target directory … .
? Which template do you want to use? cloudflare-workers
? Directory not empty. Continue? yes
✔ Cloning the template
? Do you want to install project dependencies? yes
? Which package manager do you want to use? yarn
✔ Installing project dependencies
🎉 Copied project files

wrangler.toml に👇を追加し、

[dev]
ip = "0.0.0.0"
port = 8787

コンテナ再起動して yarn devhttp://localhost:8787/ にアクセスし、「Hello Hono!」が表示されていればOKです。

完全ローカルだけの D1 環境構築

wrangler.toml に👇を追加します。

[[d1_databases]]
binding = "DB"
database_name = "trial-d1"
database_id = "1"

この時ローカルのみの環境なので database_id は空出なければ何でもいいみたいです。

試しにseedデータ登録

次に試しに👇の seed.sql を作成しときます。

CREATE TABLE IF NOT EXISTS users (
  id INTEGER PRIMARY KEY,
  name VARCHAR(50) NOT NULL);

INSERT INTO users VALUES (1,'山田 太郎');
INSERT INTO users VALUES (2,'鈴木 花子');

次にこれをローカルのD1環境に対して実行してみます。

yarn wrangler d1 execute trial-d1 --local --file=seed.sql

👆を実行すると自分の環境では .wrangler/state/v3/d1/miniflare-D1DatabaseObject/XXXX.sqlite が作成され、SQLクライアントツールで開くとちゃんと users テーブルが作成され、データが登録されていました ✨

image1.png

確認できたらこの後マイグレーションで別途テーブル作成するので、.wrangler/state/v3/d1/miniflare-D1DatabaseObject/XXXX.sqlite を削除しときます。

Prisma環境構築

先ずは必要なパッケージをインストールしていきます。

yarn add -D prisma
yarn add @prisma/client @prisma/adapter-d1

次にPrismaを初期化します。

npx prisma init --datasource-provider sqlite  

次に生成された prisma/schema.prisma に👇を追加します。

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["driverAdapters"] # ← 追加
}

最後に wrangler.toml にCloudflare WorkersでNode.jsのAPIを有効化するため👇を追加します。

name = "...."
compatibility_date = "2024-07-24"
compatibility_flags = ["nodejs_compat"]

マイグレーション

改めて users テーブルを作成すべく、先にマイグレーションファイルを作成しときます。

yarn wrangler d1 migrations create trial-d1 users

👆を実行すると手元の環境だと migrations/0001_users.sql が作成されました。

次に prisma/schema.prismausers テーブルを設定します。

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

最後にPrismaのmigrateコマンドを実行します。

yarn prisma migrate diff --from-empty --to-schema-datamodel ./prisma/schema.prisma --script --output migrations/0001_users.sql

すると空だった migrations/0001_users.sql は👇の様に更新されました。

-- CreateTable
CREATE TABLE "User" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "email" TEXT NOT NULL,
    "name" TEXT
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");

ローカルのD1へ👆のマイグレートを反映させてみます。

yarn wrangler d1 migrations apply trial-d1 --local

sqlファイルを開いてみるとちゃんと反映されています。

image2.png

ちなみに、次回以降のマイグレーションはどうするのかというと、 yarn prisma migrate diff--from-empty の部分を --from-local-d1 としてやることでローカルのD1を見にいき prisma/schema.prisma との差分を取ってくれます。

完全ローカルだけの R2 環境構築

wrangler.toml に👇を追加します。

[[r2_buckets]]
binding = "R2"
bucket_name = "trial-r2"

お試し用の seed.json を👇内容で作成します。

{
  "users": [
    {
      "name": "John Doe",
      "email": "john@example.com"
    }
  ]
}

次にこれをローカルのR2環境へputしてみます。

yarn wrangler r2 object put trial-r2/users --local --file=seed.json

実行すると自分の環境では .wrangler/state/v3/r2/my-bucket/blobs/xxxxx... が作成されていました。

objectが反映されているか /storage にアクセスするとobject一覧の情報が返るようなAPIを作成して確認してみたいと思います。

src/index.ts を👇内容に変更します。

import { Hono } from 'hono';

type Bindings = {
  DB: D1Database;
  R2: R2Bucket;
};

const app = new Hono<{ Bindings: Bindings }>();

app.get('/', (c) => {
  return c.text('Hello Hono!');
});

app.get('/r2-objects', async (c) => {
  const list = await c.env.R2.list();
  return c.text(JSON.stringify(list));
});

export default app;

http://localhost:8787/r2-objects にアクセスして先ほど登録したobjectが表示されていれば良さそうです。👇 手元で試した所作成した key: users のobjectが返ってきてました!

image3.png

参考URL

https://tech.fusic.co.jp/posts/hono-prisma-cloudflare-d1/

https://wp-kyoto.net/integrate-cloudflare-r2-from-hono/

https://github.com/einverne/hono-cloudflare-r2

Discussion