Next.js 13中使用"use client"时Zod环境变量验证失效
解决Next.js 13客户端组件中Zod环境变量验证失效问题
问题根源
你遇到的核心问题在于:
- 客户端组件(加了
"use client")只能访问以NEXT_PUBLIC_开头的环境变量,像JWT_SECRET这类敏感变量在客户端环境中根本不存在。 - 你把公开变量和私有变量放在同一个Zod Schema里解析,当客户端组件导入这个Schema时,Zod会尝试验证所有字段——包括客户端拿不到的
JWT_SECRET,直接导致验证失败。
解决方案
方案一:拆分客户端/服务端环境变量Schema
把环境变量按使用场景拆分,避免客户端验证服务端专属变量:
// src/utils/env.ts import { z } from "zod"; // 仅客户端可用的公开环境变量Schema export const clientEnv = z.object({ NEXT_PUBLIC_APIAUTH: z.string().min(1), }).parse({ NEXT_PUBLIC_APIAUTH: process.env.NEXT_PUBLIC_APIAUTH, }); // 服务端可用的全量环境变量Schema export const serverEnv = z.object({ NEXT_PUBLIC_APIAUTH: z.string().min(1), JWT_SECRET: z.string().min(1), }).parse(process.env);
然后在对应场景导入:
// src/app/signup/page.tsx(客户端组件) "use client"; import { clientEnv } from "@/utils/env"; console.log(clientEnv.NEXT_PUBLIC_APIAUTH); // 正常输出
服务端代码(如app/api目录下的文件)则导入serverEnv来使用JWT_SECRET。
方案二:根据运行环境动态解析Schema
如果不想拆分Schema,可以通过判断环境来选择性验证字段:
// src/utils/env.ts import { z } from "zod"; // 判断当前是否为服务端环境 const isServer = typeof window === "undefined"; // 基础公开变量Schema const baseSchema = z.object({ NEXT_PUBLIC_APIAUTH: z.string().min(1), }); // 服务端追加私有变量Schema const serverSchema = baseSchema.extend({ JWT_SECRET: z.string().min(1), }); // 根据环境选择解析逻辑 export const env = isServer ? serverSchema.parse(process.env) : baseSchema.parse(process.env);
这样客户端只会验证NEXT_PUBLIC_APIAUTH,服务端会验证全量变量,不会出现报错。
关键注意事项
- 确保
.env.local中的公开变量确实以NEXT_PUBLIC_开头,拼写不能出错。 - 敏感变量(如
JWT_SECRET)绝对不能在客户端组件中使用或解析,否则会直接泄露给用户。
内容的提问来源于stack exchange,提问作者Neeraj Walia
相关产品推荐
相关产品推荐

