为什么需要专门的环境变量解决方案?
2026/6/8 14:37:12 网站建设 项目流程

类型安全问题:环境变量没有类型检查,容易在运行时出错

验证缺失:无法确保必需的环境变量都已正确配置

客户端/服务端混淆:可能意外将敏感变量暴露到客户端

团队协作困难:新成员不知道需要配置哪些环境变量

T3 Env 正是为了解决这些问题而生,它提供了类型安全的环境变量管理方案。

server variables

client variables

shared variables

非法/缺失

.env

.env.local

src/env.js

createEnv({…})

Zod Schema

校验层

服务端代码

getStaticProps / API Routes …

客户端代码

浏览器 Bundle

两端共享

NODE_ENV …

运行时抛错

构建失败

核心特性

1. 类型安全的环境变量

import { createEnv } from "@t3-oss/env-nextjs";

import { z } from "zod";

const env = createEnv({

server: {

DATABASE_URL: z.string().url(),

API_SECRET: z.string().min(1),

},

client: {

NEXT_PUBLIC_API_URL: z.string().url(),

},

runtimeEnv: {

DATABASE_URL: process.env.DATABASE_URL,

API_SECRET: process.env.API_SECRET,

NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,

},

});

2. 运行时验证

库在应用启动时会自动验证所有环境变量,如果缺少必需变量或类型不匹配,会立即抛出清晰错误,而不是在运行时神秘崩溃。

3. 客户端/服务端自动隔离

通过明确的配置区分,确保服务端敏感变量不会意外泄漏到客户端。

配置指南

基础安装与配置

npm install @t3-oss/env-nextjs zod

注意:T3 Env 提供了多个包, 如 @t3-oss/env-nextjs 和 @t3-oss/env-core,分别用于 Next.js 和普通 Node.js 项目。

创建 env.js 文件:

import { createEnv } from "@t3-oss/env-nextjs";

import { z } from "zod";

export const env = createEnv({

server: {

// 服务端专用环境变量

DATABASE_URL: z.string().url(),

GITHUB_CLIENT_SECRET: z.string().min(1),

NODE_ENV: z.enum(["development", "test", "production"]),

},

client: {

// 客户端可访问的环境变量

NEXT_PUBLIC_API_BASE_URL: z.string().url(),

NEXT_PUBLIC_APP_VERSION: z.string().min(1),

},

// 运行时环境变量映射

runtimeEnv: {

DATABASE_URL: process.env.DATABASE_URL,

GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,

NODE_ENV: process.env.NODE_ENV,

NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL,

NEXT_PUBLIC_APP_VERSION: process.env.NEXT_PUBLIC_APP_VERSION,

},

// 跳过某些环境变量的验证(可选)

skipValidation: !!process.env.SKIP_ENV_VALIDATION,

});

高级验证场景

const env = createEnv({

server: {

// 复杂验证规则

PORT: z.string().regex(/^\d+$/).transform(Number),

FEATURE_FLAGS: z.string().transform((str) => str.split(',')),

MAX_UPLOAD_SIZE: z.string().default('10').transform(Number),

// 条件验证

DATABASE_URL: z.string().url().optional(),

DATABASE_HOST: z.string().min(1).optional(),

}).refine(

(data) => data.DATABASE_URL || data.DATABASE_HOST,

"Either DATABASE_URL or DATABASE_HOST must be provided"

),

});

实际应用

API 路由中的使用

// pages/api/users.ts

import { env } from "../../env";

import { NextApiRequest, NextApiResponse } from "next";

export default async function handler(

req: NextApiRequest,

res: NextApiResponse

) {

// 类型安全的环境变量访问

const databaseUrl = env.DATABASE_URL;

const apiSecret = env.API_SECRET;

// 业务逻辑...

res.status(200).json({ success: true });

}

客户端组件中的使用

// components/UserProfile.tsx

import { env } from "../env";

export function UserProfile() {

// 只能访问客户端环境变量

const apiUrl = env.NEXT_PUBLIC_API_BASE_URL;

return (

<div>

<p>API Base URL: {apiUrl}</p>

</div>

);

}

与 Next.js 配置集成

// next.config.js

const { env } = require("./env");

/** @type {import('next').NextConfig} */

const nextConfig = {

env: {

CUSTOM_KEY: "value",

},

publicRuntimeConfig: {

apiUrl: env.NEXT_PUBLIC_API_BASE_URL,

},

};

module.exports = nextConfig;

真实案例

create-t3-app

create-t3-app 是一个快速构建全栈 TypeScript 应用的脚手架,集成了 Next.js、tRPC、Prisma、Tailwind CSS 等现代工具。它以“强类型、可扩展、开发体验优先”为核心理念,帮助开发者快速搭建高质量的 Web 应用。

nahida-template

我搭建的 nahida-template,就用到了 @t3-oss/env-core。nahida-template 是基于 Elysia.js、Next.js 16 和 TypeScript 的现代全栈单仓模板,提供高性能与端到端类型安全支持。欢迎 star 和提建议。

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

import { z } from "zod"

export const env = createEnv({

shared: {

NODE_ENV: z

.enum(["development", "production", "test"])

.default("development"),

PORT: z.number().default(3001),

},

/**

* Specify your server-side environment variables schema here. This way you can ensure the app

* isn't built with invalid env vars.

*/

server: {

NODE_ENV: z

.enum(["development", "test", "production"])

.default("development"),

DATABASE_URL: z.string().url(),

BETTER_AUTH_SECRET: z.string(),

BETTER_AUTH_URL: z.string().url(),

GITHUB_CLIENT_ID: z.string(),

GITHUB_CLIENT_SECRET: z.string(),

},

/**

* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.

* middlewares) or client-side so we need to destruct manually.

*/

runtimeEnv: {

NODE_ENV: process.env.NODE_ENV,

DATABASE_URL: process.env.DATABASE_URL,

BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,

BETTER_AUTH_URL: process.env.BETTER_AUTH_URL,

GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,

GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,

// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,

},

/**

* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially

* useful for Docker builds.

*/

skipValidation: !!process.env.SKIP_ENV_VALIDATION,

/**

* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and

* `SOME_VAR=''` will throw an error.

*/

emptyStringAsUndefined: true,

})

性能与安全考量

性能

环境变量验证只在启动时进行一次

支持设置 skipValidation: true 跳过运行时验证

使用环境变量缓存避免重复初始化

安全最佳实践

永远不要将敏感信息提交到版本控制

使用不同的密钥用于开发、测试和生产环境

定期轮换密钥和密码

使用密钥管理服务(如 AWS Secrets Manager)

总结

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询