Astro + Cloudflare worker 环境变量问题

我使用的是Astro框架 + Cloudflare worker 部署,AI 给我写的代码里面充满了locals?.runtime?.env , import.meta.env ,process.env 等环境变量,通过各种测验和自己的理解,还有 AI 给的回复,整理如下:

Q:wrangler dev 和 wrangler dev —remote 有什么区别

简短区别:

  • wrangler dev
    默认本地模式(Miniflare 模拟)。快、可离线、热更新快,但有些行为和线上不完全一致(比如缓存、WebSocket、部分绑定特性、运行时差异等)。

  • wrangler dev --remote
    远程模式,代码上传到 Cloudflare 边缘运行(dev 部署)。行为更接近线上、能用真实的 KV/D1/R2 等,但速度慢一些,需要联网和登录,改动会上传。

你现在的问题如果和环境变量/运行时有关,--remote 更能反映真实环境。

Q:locals?.runtime?.env 是什么? import.meta.env 是什么 ? process.env 是什么?

下面用 Astro + Wrangler 的上下文解释:

1. locals?.runtime?.env 是什么

  • 这是 Astro Cloudflare 适配器在请求处理时注入的运行时环境变量集合。
  • 只在 Cloudflare Worker 运行时有值(包括 wrangler dev 的 worker 模式)。
  • 它来自 Worker 的 env(也就是你在 wrangler.jsoncvars、D1/KV/R2 绑定等)。
  • 只能在请求链路里拿到(middleware/API/pagecontext.locals)。

2. import.meta.env 是什么

  • Vite/Astro 在构建时注入的环境变量。
  • 在 服务端/SSR 代码里,构建时是可以把非 PUBLIC_ 的环境变量编进去的(取决于构建时环境)。
  • 会包含你允许暴露给客户端或构建的变量(在 Astro 里默认是 PUBLIC_ 前缀)。

3. process.env 是什么

  • Node.js 进程环境变量(本地开发时常见)。
  • Cloudflare Worker 运行时没有 process,所以线上/remote 模式基本不可用。
  • 本地 astro dev 可以用,但 wrangler dev 的 worker 运行时通常没有。

一句话总结:

  • 线上/wrangler dev:主要靠 locals.runtime.env
  • 本地 Node 模式:可以用 process.env
  • 构建/客户端:只能用 import.meta.env

到最后其实我还是有些糊涂,我有让AI写了一个公共函数,我不用关心到底应该写哪个 env,统一走 getEnv()函数

type EnvRecord = Record<string, string | undefined>;
type RuntimeEnvRecord = Record<string, unknown> | undefined;

let runtimeEnv: RuntimeEnvRecord = undefined;

export function setRuntimeEnv(env: RuntimeEnvRecord) {
  runtimeEnv = env;
}

function getImportMetaEnv(): EnvRecord | undefined {
  try {
    return (import.meta.env ?? {}) as EnvRecord;
  } catch {
    return undefined;
  }
}

export function getEnv(key: string): string | undefined {
  const runtimeValue = runtimeEnv?.[key];
  if (typeof runtimeValue === 'string') {
    return runtimeValue;
  }

  const metaEnv = getImportMetaEnv();
  if (metaEnv) {
    const value = metaEnv[key];
    if (value !== undefined) {
      return value;
    }
  }

  if (typeof process !== 'undefined' && process.env) {
    return process.env[key];
  }

  return undefined;
}

export function getEnvBoolean(key: string, defaultValue: boolean): boolean {
  const raw = getEnv(key);
  if (raw === undefined) {
    return defaultValue;
  }

  return raw === 'true' || raw === '1';
}

不过需要在 middleware.ts 中增加一段代码:

  if (locals?.runtime?.env) {
    setRuntimeEnv(locals.runtime.env as Record<string, unknown>);
  }
Share :

Related Posts

Astro + drizzle ORM + Cloudflare worker + D1 使用指南

在Astro + drizzle ORM + Cloudflare worker + D1 技术栈使用时,我被开发环境和 cloudflare worker 环境使用 D1 数据库 搞的晕头转向,这里记录一下。

阅读全文 →

10 天上线一个网站,一次不完美的上站经历

10 天上线一个网站,3 次技术架构重构。从 Vercel + Neon,到 Cloudflare Container,再到 Cloudflare Worker + Astro + D1,一路踩坑、调优、推翻重来。这是一篇关于性能瓶颈、冷启动误判、数据库选型与边缘计算实践的完整复盘。

阅读全文 →