项目地址:GitHub - vite-plugin-typed-env 欢迎提 Issue 和 Star ⭐
痛点:环境变量的类型噩梦
每个前端项目都有 .env 文件,里面塞满了各种配置:
env
VITE_API_URL=https://api.example.com
VITE_PORT=3000
VITE_DEBUG=true
VITE_ALLOWED_ORIGINS=http://localhost,https://example.com
然后在 vite-env.d.ts 里手写类型:
ts
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_PORT: string // 哦不,这应该是 number!
readonly VITE_DEBUG: string // 这应该是 boolean...
readonly VITE_ALLOWED_ORIGINS: string // 应该是 string[]?
}
问题来了:
.env改了,类型定义忘了改 → 类型不匹配,bug 悄悄溜进来VITE_PORT=3000明明是数字,TypeScript 却认为是字符串- 想做运行时校验?还得手写 Zod schema
- 新加的环境变量忘记声明,TypeScript 不报错,但运行时可能炸
:::tip 核心问题 类型定义和 .env 文件是两套东西,人工维护它们的一致性 = 定时炸弹 :::
解决方案:vite-plugin-typed-env
我开发了一个 Vite 插件,自动从 .env 文件生成 TypeScript 类型定义和 Zod schema。
一句话概括:写 .env,剩下的交给插件。
ts
// vite.config.ts
import envTs from 'vite-plugin-typed-env'
export default defineConfig({
plugins: [envTs()]
})
就这样,插件会自动生成:
env.d.ts- TypeScript 类型声明env.schema.ts- Zod 校验 schemaenv.ts- 运行时 loader(带校验)
核心能力一览
1. 智能类型推断
插件会根据值自动推断类型:
| 你的 .env 值 | 推断出的 TypeScript 类型 |
|---|---|
PORT=3000 |
number |
DEBUG=true |
boolean |
API_URL=https://... |
string(带 URL 校验) |
ALLOWED=1,2,3 |
number[] |
ORIGINS=a,b,c |
string[] |
生成的类型定义:
ts
interface ImportMetaEnv {
readonly PORT: number
readonly DEBUG: boolean
readonly API_URL: string
readonly ALLOWED: number[]
readonly ORIGINS: string[]
}
2. 注释指令控制
如果自动推断不够精准,可以用注释指令:
env
# @type: port
# @desc: 服务监听端口
PORT=3000
# @type: enum(info, warn, error)
LOG_LEVEL=info
# @optional
# @type: url
SENTRY_DSN=
# @type: string[]
ALLOWED_ORIGINS=http://localhost,https://example.com
生成结果:
ts
interface ImportMetaEnv {
/** 服务监听端口 */
readonly PORT: number // zod: z.coerce.number().int().min(1).max(65535)
readonly LOG_LEVEL: 'info' | 'warn' | 'error'
readonly SENTRY_DSN?: string // optional + URL 校验
readonly ALLOWED_ORIGINS: string[]
}
支持的注释指令:
| 指令 | 用途 |
|---|---|
@type: number |
强制数字类型 |
@type: boolean |
强制布尔类型 |
@type: url |
URL 格式校验 |
@type: port |
端口号校验(1-65535) |
@type: email |
邮箱格式校验 |
@type: string[] |
字符串数组 |
@type: number[] |
数字数组 |
@type: enum(a,b,c) |
联合类型枚举 |
@optional |
标记为可选 |
@default: 8080 |
设置默认值 |
@desc: 描述 |
添加 JSDoc 注释 |
3. Zod Schema 自动生成
生成的 env.schema.ts:
ts
import { z } from 'zod'
export const envSchema = z.object({
PORT: z.coerce.number().int().min(1).max(65535),
LOG_LEVEL: z.enum(['info', 'warn', 'error']),
SENTRY_DSN: z.string().url().optional(),
ALLOWED_ORIGINS: z.string().transform((v) => v.split(',').map((s) => s.trim()))
})
export type Env = z.infer<typeof envSchema>
4. 运行时校验 Loader
生成的 env.ts:
ts
import { envSchema } from './env.schema'
const _parsed = envSchema.safeParse(import.meta.env)
if (!_parsed.success) {
throw new Error('[vite-plugin-typed-env] Invalid environment variables')
}
export const env = _parsed.data
export default env
使用方式:
ts
import env from './env'
// 完全类型安全,且有运行时校验保障
console.log(env.PORT) // number
console.log(env.LOG_LEVEL) // 'info' | 'warn' | 'error'
5. 热更新支持
开发模式下,修改 .env 文件会自动重新生成类型文件,并触发 Vite 热更新。
6. import.meta.env 类型增强
默认开启,import.meta.env 自动获得完整类型:
ts
// 这也有类型了!
const port = import.meta.env.PORT // number,不是 string
快速上手
安装
bash
npm install vite-plugin-typed-env -D
npm install zod # 如果使用 Zod 校验(默认开启)
配置
ts
// vite.config.ts
import envTs from 'vite-plugin-typed-env'
export default defineConfig({
plugins: [envTs()]
})
写 .env
env
# 数据库配置
DATABASE_URL=postgres://localhost:5432/mydb
# API 密钥(可选)
# @optional
API_KEY=
# 服务端口
# @type: port
# @desc: 服务监听端口
PORT=3000
# 调试模式
# @type: boolean
DEBUG=true
# 允许的跨域来源
# @type: string[]
ALLOWED_ORIGINS=http://localhost,https://example.com
使用
ts
// 方式一:带运行时校验
import env from './env'
console.log(env.PORT) // fully typed!
// 方式二:Vite 原生方式
console.log(import.meta.env.PORT) // 同样有类型!
配置选项
ts
envTs({
// 输出目录(相对于项目根目录)
output: 'src',
// 是否生成 Zod schema
schema: 'zod' | false,
// 是否增强 import.meta.env 类型
augmentImportMeta: true,
// 缺失必填变量时是否报错
strict: true,
// 额外监听的 .env 文件
envFiles: ['.env.custom']
})
与现有方案对比
| 方案 | 类型定义 | 运行时校验 | 自动同步 | 热更新 |
|---|---|---|---|---|
手写 vite-env.d.ts |
✓ | ✗ | ✗ | ✗ |
@types/node process.env |
✓ | ✗ | ✗ | ✗ |
| dotenv + 手写 schema | ✗ | ✓ | ✗ | ✗ |
| vite-plugin-typed-env | ✓ | ✓ | ✓ | ✓ |
工作原理简图
ini
┌─────────────────────────────────────────────────────────────┐
│ .env 文件 │
│ PORT=3000 │
│ # @type: boolean │
│ DEBUG=true │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ vite-plugin-typed-env │
│ │
│ 1. 解析 .env 文件 │
│ 2. 解析注释指令 │
│ 3. 智能类型推断 │
│ 4. 生成类型文件 │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 生成三个文件 │
│ │
│ env.d.ts → TypeScript 类型声明 │
│ env.schema.ts → Zod 校验 schema │
│ env.ts → 运行时 loader(带校验) │
└─────────────────────────────────────────────────────────────┘
常见问题 FAQ
Q: 支持哪些 Vite 版本?
支持 Vite 4.x 及以上版本。
Q: Zod 是必须的吗?
不是必须的。设置 schema: false 可以跳过 Zod schema 生成,只生成类型定义。
Q: 如何处理多环境?
插件会按优先级自动合并: .env → .env.local → .env.{NODE_ENV} → .env.{NODE_ENV}.local
后面的文件会覆盖前面的同名变量。
Q: 生产环境变量缺失会怎样?
strict: true(默认)模式下,生产构建会失败并报错。开发模式下只警告。
Q: 支持非 Vite 项目吗?
目前只支持 Vite。如果你用其他构建工具,可以参考源码思路自行实现。
项目信息
- GitHub : OPBR/vite-plugin-typed-env
- npm :
vite-plugin-typed-env - License: MIT
欢迎参与
如果你觉得这个插件有用,欢迎:
- ⭐ Star 支持
- 🐛 提 Issue 反馈问题
- 🔧 提 PR 贡献代码
项目刚刚发布,还有很多可以改进的地方。如果你有好的想法,欢迎来聊!
你的 Star 是开源作者最大的动力 ⭐