Skip to content

tekihei2317/my-first-neon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

my-first-neon

Build a serverless API using Cloudflare Workers, Drizzle ORM, and Neon - Neonをやります。

目的

  • drizzle-orm、Cloudflare Workers、Neonのどれも使ったことがないので、使ってみること

知っていること

drizzle-ormは、マイグレーション機能をそなえたクエリビルダ。TypeScriptでテーブル定義を書き、そこからマイグレーションとDBクライアントを作成する感じだったと思う。

Cloudflare Workersは、エッジ関数の一種。ユーザーに近いところで処理を実行できることや、ランタイムやインフラの管理をしなくていいことにメリットがある。コールドスタートを発生させないために関数のサイズに厳しい制限があり、無料プランでは1MB以内に抑える必要がある。

Cloudflare Workersをローカルで動かすために、wranglerというツールがある。

NeonはサーバーレスのPostgreSQLで、Vercel PostgresはNeonの上に構築されている。サーバーレス関数からデータベースにアクセスする場合は、コネクションプールが使えないのが問題になる(コネクションプールはサーバー内で行われる認識)。

Prismaではこれを防ぐためのData Proxyというサービスがあるが、あまり使い勝手が良くない(日本からだと遅い)。Neonだと、接続URLを変えるだけでPgBouncerを経由していい感じにやってくれるようだ。

やってみる

バインディングとは、Workersに紐づけられたサービスなどのこと。バインディングには、KV、Queue、D1、環境変数などがある。

Neonのプロジェクトを作ってみると、Pooled connectionとDirect connectionの2つが確認できる。とりあえずDirect connectionを使ってみることにした。

drizzleのスキーマ定義、TypeScriptのフィールド名と、データベースのカラム名をマッピングできるのがいいなと思った。

生成されたマイグレーションファイルは次のとおり。CREATE TABLE IF NOT EXISTSになっているのが気になる。毎回全てのマイグレーションを実行するのだろうか。

CREATE TABLE IF NOT EXISTS "products" (
	"id" serial PRIMARY KEY NOT NULL,
	"name" text,
	"description" text,
	"price" double precision
);

processの型定義が見つからないというエラーになる。これはdotenvをインストールしていないのが原因だった。使わないけどとりあえずインストールしておく。dotenvをインポートしたら、そのファイルでprocessが使えるようになるみたいだった。どういう型定義を書いているのか後で見てみる。

Workersから環境変数DATABASE_URLを読み取れなくて、undefinedになっていた。プロセスに設定した環境変数が読み込まれるわけではないようだ。

wranglerでは、シークレットはdev.varsに設定する必要がある。設定してから再起動すると、読み込まれているというメッセージがターミナルに表示された。

wranglerでデプロイする。直後にアクセスするとのようなエラーになったが、時間が経過すると直った。

最後にDATABASE_URL環境変数を設定する。Neonのインテグレーションが用意されているので、設定からポチポチすると接続できるようになった。

気になったこと・まとめ

wranglerは、ローカルでの開発からデプロイまでをサポートしてくれるツールだった。TypeScriptのビルドを明示的にやっていないので、WorkersではESMとCJSのどちらのJSが動いているのかが気になった。"module": "es2022"なのでESM?

wranglerで環境変数を設定する場合は、wrangler.tomlに書くか、セキュアなものは.dev.varsに書く必要がある。プロセスに設定した環境変数は読み込まれないので、注意が必要。

Drizzleのマイグレーションについて。CREATE TABLE IF NOT EXISTSになっているが、毎回全てのマイグレーションが実行される訳ではなさそうだ。CREATE TABLEに変更してもエラーは出ないし、_drizzle_migrationsテーブルにマイグレーションの履歴もある。確かに、毎回全部実行するとカラムのRENAMEの2回目はエラーになるので、それはできないなと気づいた。

Drizzleについて。カラムの名前とTypeScriptの型を分けられるのはいいところかなと思った。DBはスネークケース、TypeScriptはキャメルケースみたいなのができる。

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  userName: text('user_name').notNull(),
});

クエリビルダは、selectを先に書くことや、その中身が独特だと感じた。型のエイリアスを設定できるのは便利かもしれないが、実行時エラーを防ぎにくくなっているのではないかと思う。

import { products } from './db/schema';
const result = await db
	.select({
		id: products.id,
		price: products.price,
	})
	.from(products);

例えば、FROM句で選択していないテーブルをselectで選択することをコンパイル時に防げない。select({ userId: users.id })みたいに書くと実行時エラーになる。FROMを最初に書くのがベターだと思うので、個人的には合わなさそうだなと感じた。

CloudflareもNeonもダッシュボードが綺麗でいいなと思った。

Neonのリージョンは一番近いSingaporeに作っても、レイテンシが300~400msくらいありそうだった。まだちょっと使うのはしんどいかもしれない。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published