字
字节笔记本
2026年5月3日
TanStack Start - Environment Variables 环境变量
API中转
¥120
TanStack Start 基于 Vite,使用 Vite 的环境变量约定。本文介绍环境变量的配置、使用和安全最佳实践。
快速开始
.env 文件
bash
# .env
# 服务端专用(服务端函数、API 路由)
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
API_SECRET=super_secret_key
# 客户端可访问(通过 import.meta.env.VITE_*)
VITE_APP_TITLE=My App
VITE_API_URL=https://api.example.com环境变量前缀规则
| 前缀 | 环境 | 示例 |
|---|---|---|
| 无前缀 | 仅服务端 | DATABASE_URL |
VITE_ | 服务端 + 客户端 | VITE_API_URL |
服务端上下文
Server Functions(服务端函数)
tsx
import { createServerFn } from '@tanstack/react-start'
export const getUser = createServerFn()
.handler(async () => {
// ✅ 服务端可访问所有环境变量
const dbUrl = process.env.DATABASE_URL
const secret = process.env.API_SECRET
return fetch(dbUrl).then(res => res.json())
})Loaders(路由加载器)
tsx
export const Route = createFileRoute('/posts')({
loader: async () => {
// ⚠️ loader 在服务端和客户端都运行
// 仅在 loader 内部使用服务端变量,不要暴露到客户端
const data = await fetch(`${process.env.API_SECRET}/posts`)
return data.json()
}
})客户端上下文
Components(组件)
tsx
function App() {
// ✅ 客户端组件通过 import.meta.env 访问 VITE_ 前缀变量
const apiUrl = import.meta.env.VITE_API_URL
const title = import.meta.env.VITE_APP_TITLE
return <div>{title} - API: {apiUrl}</div>
}环境文件设置
文件优先级
text
.env # 所有情况下都加载
.env.local # 所有情况下都加载,被 git 忽略
.env.[mode] # 特定模式下加载(如 .env.production)
.env.[mode].local # 特定模式下加载,被 git 忽略常见模式
数据库配置
tsx
import { createServerFn } from '@tanstack/react-start'
export const dbQuery = createServerFn()
.inputValidator((query: string) => query)
.handler(async ({ data: query }) => {
const db = new Database(process.env.DATABASE_URL)
return db.execute(query)
})认证设置
bash
# .env
AUTH_SECRET=your_jwt_secret_here
AUTH_PROVIDER_URL=https://auth.example.com
VITE_AUTH_ENABLED=trueAPI 集成
tsx
// ✅ 好模式:服务端函数处理敏感 API 调用
export const fetchSecureData = createServerFn()
.handler(async () => {
const apiKey = process.env.SECRET_API_KEY // 仅服务端
return fetch(`https://api.example.com/data?key=${apiKey}`)
})
// ❌ 避免:在客户端暴露密钥
const response = await fetch(`https://api.example.com/data?key=${import.meta.env.VITE_SECRET_KEY}`)Feature Flags(功能开关)
tsx
function FeatureFlag() {
const isNewUI = import.meta.env.VITE_ENABLE_NEW_UI === 'true'
return isNewUI ? <NewUI /> : <LegacyUI />
}类型安全
TypeScript 声明
创建 src/vite-env.d.ts 文件:
typescript
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_URL: string
readonly VITE_ENABLE_NEW_UI: 'true' | 'false'
}
interface ImportMeta {
readonly env: ImportMetaEnv
}安全最佳实践
1. 敏感数据处理
tsx
// ✅ 好模式:敏感数据留在服务端
export const secureOperation = createServerFn()
.handler(async () => {
const apiKey = process.env.SECRET_API_KEY
const dbPassword = process.env.DB_PASSWORD
// 执行敏感操作...
})
// ❌ 避免:暴露敏感数据到客户端
// VITE_SECRET_API_KEY=super_secret // 会被打包到客户端 bundle!2. Git 忽略规则
gitignore
# .gitignore
.env.local
.env.*.local
.env.development.local
.env.test.local
.env.production.local生产环境检查清单
- 检查 .env 文件: 确保所有必要环境变量已设置
- 验证敏感数据: 确保 API 密钥、数据库密码等使用无前缀变量
- 客户端变量: 确保公开变量使用
VITE_前缀 - 类型声明: 更新 TypeScript 声明文件
- Git 忽略: 确保
.env.local和敏感文件被忽略 - 平台配置: 在 Vercel、Netlify 等平台设置环境变量
环境变量对比
| 特性 | 无前缀 | VITE_ 前缀 |
|---|---|---|
| 访问环境 | 仅服务端 | 服务端 + 客户端 |
| 客户端访问 | ❌ undefined | ✅ import.meta.env.VITE_* |
| 用途 | 敏感数据、数据库、API 密钥 | 公开 API URL、功能开关 |
| 安全 | ✅ 不暴露到客户端 bundle | ⚠️ 会被打包到客户端 bundle |
常见模式
| 模式 | 服务端 | 客户端 |
|---|---|---|
| 数据库配置 | DATABASE_URL | - |
| API 密钥 | API_SECRET_KEY | - |
| API URL | API_URL | VITE_API_URL |
| 功能开关 | FEATURE_X_ENABLED | VITE_FEATURE_X_ENABLED |
分享: