Closed7

Remix Vite × Drizzle × Cloudflare D1 スタックを試してみる

KeiKei

プロジェクト作成 〜 ローカル開発の準備まで

上記サイトに従って、まずは公式テンプレートよりプロジェクト作成する

npx create-remix@latest --template remix-run/remix/templates/vite-cloudflare

早速エラーが出た。公式にtemplates/vite-cloudflareというリポジトリはないっぽいね。

npx create-remix@latest --template remix-run/remix/templates/vite-cloudflare

 remix   v2.8.1 💿 Let's build a better website...

   dir   Where should we create your new project?
         remix-vite-drizzle-cloudflare-d1

      ◼  Template: Using remix-run/remix/templates/vite-cloudflare...
 ██████  Template copying...

      ▲  Oh no! The path "templates/vite-cloudflare" was not found in this GitHub repo.

公式ドキュメントを見たところ、templates/cloudflareに変わってたのでこちらを使用

npx create-remix@latest --template remix-run/remix/templates/cloudflare

今回はうまくいった👍

npx create-remix@latest --template remix-run/remix/templates/cloudflare

 remix   v2.8.1 💿 Let's build a better website...

   dir   Where should we create your new project?
         remix-vite-drizzle-cloudflare-d1

      ◼  Template: Using remix-run/remix/templates/cloudflare...
      ✔  Template copied

   git   Initialize a new git repository?
         Yes

  deps   Install dependencies with npm?
         Yes

      ✔  Dependencies installed

      ✔  Git initialized

  done   That's it!

         Enter your project directory using cd ./remix-vite-drizzle-cloudflare-d1
         Check out README.md for development and deploy instructions.

         Join the community at https://rmx.as/discord

ドキュメントによると、アプリをローカルで起動させる方法としては下記の2つがあるようで。

# Viteの場合
remix vite:dev

# Wranglerの場合
remix vite:build # build app before running wrangler
wrangler pages dev ./build/client

下記のような記載も書かれていた。
最終的にはCloudflarePagesにデプロイするので、Wranglerを使ったローカル開発をしたほうがいいのかもしれん。いったん従ってみよう。

While Vite provides a better development experience, Wrangler provides closer emulation of the Cloudflare environment by running your server code in Cloudflare's workerd runtime instead of Node.
(日本語訳)> Viteはより良い開発体験を提供しますが、WranglerはNodeの代わりにCloudflareのworkerdランタイムでサーバーコードを実行することで、よりCloudflare環境に近いエミュレーションを提供します。

まずはビルドする

npm run build

> build
> remix vite:build

vite v5.2.7 building for production...
✓ 83 modules transformed.
build/client/.vite/manifest.json                1.02 kB │ gzip:  0.29 kB
build/client/assets/_index-CMV5dfNo.js          0.72 kB │ gzip:  0.42 kB
build/client/assets/root-CdN9S7dO.js            1.44 kB │ gzip:  0.84 kB
build/client/assets/jsx-runtime-BlSqMCxk.js     8.09 kB │ gzip:  3.04 kB
build/client/assets/entry.client-CmAxv4Nw.js   57.28 kB │ gzip: 19.52 kB
build/client/assets/components-CT78CVRP.js    178.40 kB │ gzip: 57.10 kB
✓ built in 858ms
vite v5.2.7 building SSR bundle for production...
✓ 5 modules transformed.
build/server/.vite/manifest.json  0.15 kB
build/server/index.js             4.63 kB
✓ built in 27ms

次にwranglerコマンドで起動させようとしたが、そもそもコマンド自体が入っていなかった。

wrangler pages dev ./build/client
zsh: command not found: wrangler

wranglerコマンドをインストールする
※あとから見返したら、すでにインストールされていたのでしなくてもいい。

npm install wrangler --save-dev

https://developers.cloudflare.com/workers/wrangler/install-and-update/
再度、ローカルで立ち上げてみるとうまくいった。

npm run start

> start
> wrangler pages dev ./build/client

▲ [WARNING] No compatibility_date was specified. Using today's date: 2024-03-31.

  Pass it in your terminal:
  
  --compatibility-date=2024-03-31
  
  See https://developers.cloudflare.com/workers/platform/compatibility-dates/ for more information.


Compiling worker to "/Users/takidakeiichiro/Documents/code/Remix-Project/remix-vite-drizzle-cloudflare-d1/.wrangler/tmp/pages-rY3c5G/functionsWorker-0.8071847245483197.mjs"...
✨ Compiled Worker successfully
 ⛅️ wrangler 3.41.0
-------------------
[wrangler:inf] Ready on http://localhost:8787
⎔ Starting local server...

とりあえず作成したリポジトリはこちらです。
https://github.com/otaki0413/remix-vite-drizzle-cloudflare-d1

KeiKei

Drizzle ORM のセットアップ

まずDrizzleとは?

  • Drizzle は軽量でモダンな TypeScript ORM
  • 設計上サーバーレスに対応しており、NodeJS、Bun、Deno、Cloudflare Workers、Supabase functions、あらゆるエッジランタイム、そしてブラウザーなど、主要なJSランタイムで動作する。

https://orm.drizzle.team/docs/overview

実際にインストールしてみる

必要なパッケージは以下の2つ

npm i drizzle-orm
npm i -D drizzle-kit

drizzle-kit

  • SQLマイグレーション自動生成とラピッドプロトタイピングのためのCLIコンパニオン。
  • スキーマを異なるファイルに分割したり、1つのプロジェクトで異なるDB用の複数スキーマを作成できる。

スキーマの作成

インストールしたら、基本的なスキーマを書いてみる。

app/drizzle/schema.server.ts
import {
  sqliteTable,
  text,
  integer,
} from "drizzle-orm/sqlite-core"
export const resources = sqliteTable("resources", {
  id: integer("id").primaryKey(),
  title: text("title").notNull(),
  href: text("href").notNull(),
})

スクリプト設定 + 実行

スキーマに基づいて型を生成するために、drizzle-kitを使用する。
package.jsonにマイグレーションを実行するスクリプトを追加

package.json
{
  "scripts": {
    "drizzle:update": "drizzle-kit generate:sqlite --out ./app/drizzle/migrations --schema ./app/drizzle/schema.server.ts"
  }
}

スクリプト実行すると、migrationsフォルダが生成され、その配下にマイグレーションファイルができる

npm run drizzle:update

> drizzle:update
> drizzle-kit generate:sqlite --out ./app/drizzle/migrations --schema ./app/drizzle/schema.server.ts

drizzle-kit: v0.20.14
drizzle-orm: v0.30.6

1 tables
resources 3 columns 0 indexes 0 fks

[] Your SQL migration file ➜ app/drizzle/migrations/0000_worthless_cardiac.sql 🚀

このあたりが参考になるか
https://orm.drizzle.team/docs/get-started-sqlite#cloudflare-d1

KeiKei

D1のセットアップ

データベース作成

下記コマンドでデータベースを新規作成できる

npx wrangler d1 create <データベース名>

test-dbという名前で試しに作る

Cloudflareのダッシュボードを確認したところ、ちゃんとできてるみたい

データベース作成時にコマンド出力された内容をwrangler.tomlに貼り付ける。
漏れてほしくいない情報だと思うので、本ファイルを.gitignoreにも追記しておく。

wrangler.toml
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "test-db"
database_id = "データベースID"
migrations_dir="./app/drizzle/migrations" 👈️ これは追記しておく

データベースのインターフェース作成

データベースが存在することをTypeScriptに伝えるために、下記コマンドでインターフェース生成する

npx wrangler types
 ⛅️ wrangler 3.41.0
-------------------
interface Env {
	DB: D1Database;
}

すると、worker-configuration.d.tsができる

worker-configuration.d.ts
// Generated by Wrangler on Sun Mar 31 2024 15:21:05 GMT+0900 (Japan Standard Time)
// by running `wrangler types`

interface Env {
	DB: D1Database;
}

その後、プロジェクト作成時から存在するload-context.tsに、空のEnvインターフェースがあるが、
上記で生成されたものを機能させたいのでこちらは削除しておく。

load-context.ts
import { type PlatformProxy } from "wrangler";

- interface Env {} 

type Cloudflare = Omit<PlatformProxy<Env>, "dispose">;

declare module "@remix-run/cloudflare" {
  interface AppLoadContext {
    cloudflare: Cloudflare;
  }
}

PagesFunctionsとD1の紐づけ

プロジェクトの[setting] > [Functions] > [D1 database bindings]の部分で設定する。
とりあえず変数名はDBとして、値はD1のデータベースを選択する。


この設定により、本番の Pages Functions(Workers) からも D1 へ接続ができるようになる。

KeiKei

マイグレーションの適用

ローカルでの適用 --local

マイグレーションの一覧確認

npx wrangler d1 migrations list test-db
 ⛅️ wrangler 3.41.0
-------------------
Migrations to be applied:
┌────────────────────────────┐
│ Name                       │
├────────────────────────────┤
│ 0000_worthless_cardiac.sql │
└────────────────────────────┘

マイグレーションが作成済みなので、まずはローカル環境に適用させる。--local忘れずに。

npx wrangler d1 migrations apply test-db --local
 ⛅️ wrangler 3.41.0
-------------------
Migrations to be applied:
┌────────────────────────────┐
│ name                       │
├────────────────────────────┤
│ 0000_worthless_cardiac.sql │
└────────────────────────────┘
✔ About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? … yes
🌀 Mapping SQL input into an array of statements
🌀 Executing on local database test-db (635dc2a7-6ff1-4154-b7d7-67b64f186783) from .wrangler/state/v3/d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
┌────────────────────────────┬────────┐
│ name                       │ status │
├────────────────────────────┼────────┤
│ 0000_worthless_cardiac.sql │ ✅       │
└────────────────────────────┴────────┘

再度マイグレーション確認したが、もう残ってないのでOK。

npx wrangler d1 migrations list test-db
 ⛅️ wrangler 3.41.0
-------------------
✅ No migrations to apply!

本番での適用

--localオプションを外す (👈️これ機能しない)

npx wrangler d1 migrations apply test-db
 ⛅️ wrangler 3.41.0
-------------------
✅ No migrations to apply!

あれ、マイグレーションがない???本番DBに適用されると思っていたが想定していた動きと違う。
いったんドキュメント見るか。

下記はマイグレーション適用のコマンド。

wrangler d1 migrations apply <DATABASE_NAME> [OPTIONS]
  • --local
    • デフォルト設定
    • ローカルに永続化されたD1データベースに対して、未適用のマイグレーションを実行する。
  • --remote
    • リモート D1 データベースに対して、未適用のマイグレーションを実行する

https://developers.cloudflare.com/workers/wrangler/commands/#migrations-apply

--remoteつけて再度実行したらうまくいった!✨

npx wrangler d1 migrations apply test-db --remote
KeiKei

デプロイ

下記コマンドでデプロイできる。

npm run deploy

> deploy
> wrangler pages deploy ./build/client

No project selected. Would you like to create one or use an existing project?
❯ Create a new project
  Use an existing project
✔ Enter the name of your new project: … remix-vite-drizzle-cloudflare-d1
✔ Enter the production branch name: … main
✨ Successfully created the 'remix-vite-drizzle-cloudflare-d1' project.
✨ Compiled Worker successfully
🌎  Uploading... (8/8)

✨ Success! Uploaded 8 files (2.04 sec)

✨ Uploading Functions bundle
✨ Deployment complete! Take a peek over at https://2ae1b2ba.remix-vite-drizzle-cloudflare-d1.pages.dev

最終行のリンクより、アクセスできればデプロイは完了!
https://remix-vite-drizzle-cloudflare-d1.pages.dev/

このスクラップは2024/03/31にクローズされました