🧷

Hono on Cloudflare Workersではprocess.envの代わりにc.envを使う

に公開

個人開発でHono on Cloudflare Workersな構成でAPIを開発しています。

問題

.dev.varsに環境変数を書き、wrangler devで開発サーバーを起動すると、DBへの接続ができずエラーが発生してしまいました。

import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";

export const env = createEnv({
  server: {
    ...
    DATABASE_URL: z.string().url(),
  },
  runtimeEnv: process.env,
});

調査すると環境変数がundefinedのままになっていることが原因でした。
環境変数は渡しているはずだし、作業用のスクリプトには環境変数が設定されておりうまく動いています。

※t3-envを使っているのは環境変数にも型をつけるためです。
t3-envを使わずprocess.envに直接アクセスしようとしても同じ問題がおきます。

解決方法

公式ドキュメントにCloudflare Workersでは、環境変数はprocess.envではなくc(コンテキスト)経由で取得する必要がる旨が書かれていました。

For Cloudflare Workers, environment variables must be obtained via c, not via process.env.

https://hono.dev/docs/getting-started/cloudflare-workers#load-env-when-local-development

次のように、Bindingsに環境変数の型を設定し、c.env.XXXのように環境変数にアクセスできます。

Cloudflare WorkersがEdge環境で動き、リクエストごとに異なるマシンで動くための制約でしょうか

type Bindings = {
  SECRET_KEY: string
}

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

app.get('/env', (c) => {
  const SECRET_KEY = c.env.SECRET_KEY
  return c.text(SECRET_KEY)
})

ちなみにwrangler typesコマンドを使うと、.dev.varsを読み取って型定義ファイル(worker-configuration.d.ts)を生成してくれるので、Bindings型を定義する必要もありません。

ドキュメントの手順に従い、tsconfig.jsonを設定した上で次のように書くことができます。

// tsconfig.json
    ...
    "types": ["./worker-configuration.d.ts"],
    ...
import { Hono } from "hono";

const app = new Hono<{ Bindings: Env }>() // Envがworker-configuration.d.tsに宣言されている

app.get('/env', (c) => {
  const SECRET_KEY = c.env.SECRET_KEY
  return c.text(SECRET_KEY)
})

https://developers.cloudflare.com/workers/languages/typescript/

Discussion