ByteNoteByteNote

字节笔记本

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=true

API 集成

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_ 前缀
访问环境仅服务端服务端 + 客户端
客户端访问❌ undefinedimport.meta.env.VITE_*
用途敏感数据、数据库、API 密钥公开 API URL、功能开关
安全✅ 不暴露到客户端 bundle⚠️ 会被打包到客户端 bundle

常见模式

模式服务端客户端
数据库配置DATABASE_URL-
API 密钥API_SECRET_KEY-
API URLAPI_URLVITE_API_URL
功能开关FEATURE_X_ENABLEDVITE_FEATURE_X_ENABLED
分享: