Supabase 环境变量在生产缺失

URL / anon key undefined——宿主 env / 前缀 / 缓存。

你本地 .env 里有 NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY,调用 createClient(url, anonKey) 正常工作。部署到 Vercel / Netlify / Cloudflare Pages 后,前端 console 报:

TypeError: Cannot read properties of undefined (reading 'auth')
Error: supabaseUrl is required.

或者更安静——所有 Supabase 调用 silently 失败,页面看似加载但没数据。这是部署平台没拿到 env、或前缀不对、或 build cache 旧导致的”process.env.X 在 client bundle 里是 undefined”。

理解关键:env vars 不会”自动从 .env 同步到云”。每个平台都要单独配置;前端 bundle 里能用的 env 必须有特定前缀(NEXT_PUBLIC_ / VITE_ / PUBLIC_)。

常见原因

按命中率从高到低:

1. 部署平台压根没设这两个 env

最高频。你本地有 .env,但 Vercel dashboard 里完全没添加。.env 不在 git(也不该在),所以部署后 process.env.X === undefined

如何判断:Vercel / Netlify / CF Pages 的 dashboard → Environment Variables → 看是否存在。

2. 前缀和框架不匹配

Next.js → NEXT_PUBLIC_X     (client 端可见)
Vite    → VITE_X            (import.meta.env.VITE_X)
Astro   → PUBLIC_X          (import.meta.env.PUBLIC_X)
SvelteKit → PUBLIC_X        ($env/static/public)
Remix   → 不强制前缀,但建议用 PUBLIC_

少了前缀的 env 不会被打进 client bundle,访问就是 undefined。

如何判断:你的 env 名称带正确前缀吗?

3. build cache 缓存了旧 env

你刚刚加了 env,但 Vercel 用 cached build artifact 部署 → bundle 里仍然没有新 env。

如何判断:刚改完 env 立刻 redeploy 但问题没解决。

4. 只设了 Preview,没设 Production

Vercel 的 env scope 分 Development / Preview / Production。只勾了 Preview,Production 部署照样 undefined。

如何判断:Vercel dashboard 里看每个 env var 的 environment 勾选范围。

5. 用了 server-side only env 在 client 端

SUPABASE_SERVICE_ROLE_KEY(不带 NEXT_PUBLIC_ 前缀)在 server 才能读,client 端访问就是 undefined——而且这是好事,service role key 绝不能给 client。

如何判断:你试图在 client component 读 server-only env。

6. env value 末尾有空格 / 换行

复制 anon key 时多带了空格或换行符,初始化时 URL parse 失败。

如何判断:手动 trim 看是否解决。

最短修复路径

Step 1:到 Supabase 后台复制正确值

Supabase Dashboard → Project → Settings → API
  → Project URL(https://xxx.supabase.co)
  → anon public key(eyJ...长串)

注意复制时不要带前后空格。

Step 2:到部署平台添加 env

Vercel:
  Settings → Environment Variables
  → Add NEXT_PUBLIC_SUPABASE_URL = https://xxx.supabase.co
  → Add NEXT_PUBLIC_SUPABASE_ANON_KEY = eyJ...
  → Environment: 勾 Production + Preview + Development(都勾)

Netlify:
  Site settings → Environment variables → Add a variable

Cloudflare Pages:
  Settings → Environment variables → Production

确认所有环境(Production / Preview / Development)都勾上。

Step 3:grep 代码确认前缀

# Next.js
grep -r "process.env.SUPABASE" src/
# 应该都是 process.env.NEXT_PUBLIC_SUPABASE_*

# Vite
grep -r "import.meta.env" src/
# 应该都是 import.meta.env.VITE_SUPABASE_*

# Astro
grep -r "import.meta.env" src/
# 应该都是 import.meta.env.PUBLIC_SUPABASE_*

不匹配的改对:

// Next.js
const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

Step 4:强制重新部署(清 cache)

Vercel:
  Deployments → 最新 → ... → Redeploy
  → 取消勾选 "Use existing Build Cache"

Netlify:
  Deploys → Trigger deploy → "Clear cache and deploy site"

Cloudflare Pages:
  自动用最新 commit,但可以 force:retry deployment

Step 5:线上验证

打开生产 URL,DevTools Console:

// Next.js
console.log(process.env.NEXT_PUBLIC_SUPABASE_URL);
// 应输出 https://xxx.supabase.co,不是 undefined

// Vite
console.log(import.meta.env.VITE_SUPABASE_URL);

如果还 undefined → 前缀不对或 build cache 没清。

Step 6:boot-time 校验

加 fail-fast 校验,下次缺失立刻 build 失败而非 runtime 错:

// lib/env.ts
import { z } from 'zod';

const envSchema = z.object({
  NEXT_PUBLIC_SUPABASE_URL: z.string().url(),
  NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().min(20),
});

export const env = envSchema.parse({
  NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
  NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
});

build 时缺 env 直接挂,比 runtime 才发现强 10 倍。

Step 7:server-only env 分清

// ✅ client 可见
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY

// ❌ 只 server 用,绝对不能加 NEXT_PUBLIC_ 前缀
SUPABASE_SERVICE_ROLE_KEY  // service role 有完全 DB 权限,泄露 = 灾难

预防建议

  • README / CLAUDE.md 列出所有必须 env,包括前缀
  • 项目根放一个 .env.example(不含真值)跟 .env 同步,新人 clone 后照着配
  • 用 zod 在 boot 时校验 env,缺失立刻 fail-fast
  • 任何含 _KEY_SECRET_TOKEN 的 env 永远不加 NEXT_PUBLIC_ / VITE_ / PUBLIC_ 前缀
  • 加新 env 时立刻同步本地、Preview、Production 三处
  • 改完 env 习惯性 “Clear cache and redeploy”,别假设增量 build 会带新值
  • env 改动加到 PR template / deploy checklist,避免漏配
  • 监控 boot logs,发现 env 校验失败立刻 alert

相关阅读

标签: #后端 #排查 #排查 #Supabase