しばらくハマったのでメモ
astroのapiにて、gemini api keyを使うため、シークレット変数として参照しかったが、ローカル開発のときに指定したimport.meta.env
での参照がデプロイ先のcloudflare workerにて環境変数を設定しても空になっていたので混乱した。環境変数の埋め込みタイミングの違いにより参照方法が変わるのでメモしておく
解決方法としてはlocalsを使ってenvの値を参照するとよい
ドキュメントのこの部分を読めば自明なのだが、apiに関するコードがかかれてなかったので、スルーしてしまっていた
https://docs.astro.build/en/guides/middleware/#storing-data-in-contextlocals
環境
- node: 20
- astro: 5.13.2
- wrangler: 4.31.0
確認
以下のようなAPIを作成して確認する
// src/pages/api/env.ts
export const prerender = false; // ssr
import type { APIRoute } from "astro";
// echo server
export const GET: APIRoute = async ({ url, locals }) => {
const searchQuery = url.searchParams.get("query");
const localsProjectId = locals.runtime?.env.MY_VAR;
const metaProjectId = import.meta.env.MY_VAR;
return new Response(JSON.stringify({ searchQuery, localsProjectId, metaProjectId }), {
headers: { "Content-Type": "application/json" },
});
}
- local環境
npm run dev
別コンソールにて。どちらも.envにはいった値が表示される
curl http://localhost:4321/api/env
{"searchQuery":null,"localsProjectId":"env-my-var","metaProjectId":"env-my-var"}
- デプロイ先
cloudflareのURLに対して呼び出すと、import.meta.envの値は空のため返ってこない。localsの値はcloudflareの設定画面から作成したもの
curl https://xxxx.workers.dev/api/echo
{"searchQuery":null,"localsProjectId":"env-cf-var"}
仕組み
ついでに環境変数の設定場所と関係性もまとめておく
ローカル開発環境(npm run dev)では
.envの中身を見るためlocalsでも、import.metaでも同様の値が取得できる
プレビュー環境(ローカルでbuildしたものをastro previewするときなど)も同様
表にするとこう
環境 | 設定方法 | 参照方法 | 補足 |
---|---|---|---|
ローカル開発(astro dev、wrangler dev、astro preview) | .env や .env.development | import.meta.env.MY_VAR | Vite がビルド時に注入するので動く。SSRでも値が埋め込まれる |
本番環境(wrangler deploy、astro build) | wrangler.toml [vars] / wrangler secret put | locals.runtime.env.MY_VAR | Cloudflare が runtime で env を注入。SSRにおいてimport.meta.env はビルド済み定数なので undefined |
いくつか補足
- cloudflare workerでは、環境変数をbuild時に渡すのではなく、runtimeに入れ込む様子(なので、context.locals.envという名称がついている)。そのためSSRのサーバー側にて参照する環境変数はクライアント側にある
import.meta.env
ではなくlocalsから参照しないといけない - publicな(クライアントサイドで参照する環境変数)であればprefixにPUBLIC_MY_VARなどとして
wrangler.toml [vars]
に設定することで参照可能となる - astroにはMODEという概念があり(devで起動しているかbuildしたものをみているかで変わる)
import.meta.env.MODE
でどちらかを参照可能。MODEの違いにより.env.development
や、.env.production
などといった名称でも環境変数が参照可能になっている