📘

Vercel Postgresのローカル環境構築

に公開

Next.jsのApp Routerのサンプルの dashboardアプリ はVercelのPostgresを利用するようになっているが、少し変更を加えればローカル環境のPostgresも使えるようなのでやってみた。
なおVercel PostgresではWebSocketを利用しているようだ。

以下の作業が必要。

  • compose.yamlの追加
  • .envの指定
  • ライブラリの追加
  • ラッパーライブラリ (app/lib/db.ts) の追加

compose.yamlの追加

このコメント に従ってcompose.yamlを作成し、WebSocketのproxyを立てる。
psqlでも psql -h localhost -U postgres -p 54320 でアクセス可能。

compose.yaml
version: '3'
services:
  postgres:
    image: postgres:16
    container_name: nextjs-db
    environment:
      POSTGRES_PASSWORD: password
    ports:
      - "54320:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
  pg_proxy:
    image: ghcr.io/neondatabase/wsproxy:latest
    container_name: nextjs-db-proxy
    environment:
      APPEND_PORT: "postgres:5432"
      ALLOW_ADDR_REGEX: ".*"
      LOG_TRAFFIC: "true"
    ports:
      - "54330:80"
    depends_on:
      - postgres
volumes:
  pgdata:

.envの指定

以下の内容を追記する。

VERCEL_ENV=development
POSTGRES_URL=postgresql://postgres:password@localhost:54320/postgres

ライブラリの追加

@neondatabase/serverless を追加する。今のところバージョン1.0では下のパッチが動作しないようなので0.9を指定する。

$ pnpm i -D @neondatabase/serverless@0.9

ラッパーライブラリの追加

このコメント に従って app/lib/db.ts を作成する。
sql 関数は neonConfig を反映しないので置換が必要。このコメント を参考に作成し、clientsql をexportする。

app/lib/db.ts
import { db } from '@vercel/postgres';
import { neonConfig, QueryResult, QueryResultRow } from "@neondatabase/serverless";

type Primitive = string | number | boolean | undefined | null;

if (process.env.VERCEL_ENV === "development") {
  neonConfig.wsProxy = (host) => `${host}:54330/v1`;
  neonConfig.useSecureWebSocket = false;
  neonConfig.pipelineTLS = false;
  neonConfig.pipelineConnect = false;
}

export const client = await db.connect();

export function sql<T extends QueryResultRow>(
    strings: TemplateStringsArray,
    ...values: Primitive[]
): Promise<QueryResult<T>> {
  return client.sql(strings, ...values);
}

利用方法

docker compose up -D でPostgresを起動しておく。
あとは vercel/postgres の代わりに @/app/lib/db を使う。

参考情報

Discussion