Skip to content

Bun 环境变量

Bun 提供了强大的环境变量管理功能,自动加载 .env 文件,并提供多种访问方式。本章介绍 Bun 环境变量的使用方法。

自动加载 .env 文件

基本用法

Bun 会自动加载项目根目录的 .env 文件:

bash
# .env
APP_NAME=我的应用
APP_PORT=3000
DATABASE_URL=postgresql://localhost:5432/mydb
API_KEY=your-secret-key-here
DEBUG=true
typescript
// app.ts
console.log(Bun.env.APP_NAME);     // "我的应用"
console.log(Bun.env.APP_PORT);     // "3000"
console.log(Bun.env.DATABASE_URL); // "postgresql://localhost:5432/mydb"

运行:

bash
bun app.ts

加载顺序

Bun 按以下顺序加载环境变量(后面的会覆盖前面的):

  1. 系统环境变量
  2. .env 文件
  3. .env.local 文件
  4. .env.development / .env.production(根据 NODE_ENV)
  5. .env.development.local / .env.production.local

访问环境变量

使用 Bun.env

typescript
// Bun 推荐方式
const appName = Bun.env.APP_NAME;
const port = Bun.env.APP_PORT;

// 带默认值
const debug = Bun.env.DEBUG ?? "false";
const timeout = Bun.env.TIMEOUT || "5000";

使用 process.env

typescript
// Node.js 兼容方式
const appName = process.env.APP_NAME;
const port = process.env.APP_PORT;

// 与 Bun.env 等价
console.log(Bun.env === process.env); // true

类型安全访问

typescript
// 定义环境变量接口
interface Env {
  APP_NAME: string;
  APP_PORT: string;
  DATABASE_URL: string;
  API_KEY: string;
  DEBUG?: string;
}

// 类型断言
const env = Bun.env as unknown as Env;

// 或创建配置对象
const config = {
  appName: Bun.env.APP_NAME!,
  port: parseInt(Bun.env.APP_PORT || "3000"),
  databaseUrl: Bun.env.DATABASE_URL!,
  apiKey: Bun.env.API_KEY!,
  debug: Bun.env.DEBUG === "true",
};

多环境配置

环境文件

bash
# .env - 所有环境共享
APP_NAME=我的应用

# .env.development - 开发环境
NODE_ENV=development
API_URL=http://localhost:3000
DEBUG=true

# .env.production - 生产环境
NODE_ENV=production
API_URL=https://api.example.com
DEBUG=false

# .env.local - 本地覆盖(不提交到 Git)
API_KEY=my-local-key

.gitignore 配置

gitignore
# 不要提交敏感的本地配置
.env.local
.env.*.local
.env.development.local
.env.production.local

指定环境文件

bash
# 使用 --env-file 指定文件
bun --env-file .env.staging app.ts

# 可以多次使用
bun --env-file .env --env-file .env.staging app.ts

环境变量语法

基本语法

bash
# 简单赋值
KEY=value

# 带引号(保留空格)
MESSAGE="Hello World"
SINGLE='Hello World'

# 多行值
MULTILINE="Line 1
Line 2
Line 3"

# 空值
EMPTY=
EMPTY_QUOTED=""

变量引用

bash
# 引用其他变量
BASE_URL=https://api.example.com
API_ENDPOINT=${BASE_URL}/v1

# 带默认值
PORT=${APP_PORT:-3000}
HOST=${APP_HOST:-localhost}

注释

bash
# 这是注释
APP_NAME=myapp  # 行尾注释

# 跨行注释
# API_KEY=old-key
API_KEY=new-key

转义字符

bash
# 包含特殊字符
PASSWORD="pass\$word"
PATH_WITH_SPACES="/path/to/my\ folder"

配置验证

启动时验证

typescript
// config.ts
function getRequiredEnv(key: string): string {
  const value = Bun.env[key];
  if (!value) {
    throw new Error(`缺少必需的环境变量: ${key}`);
  }
  return value;
}

function getOptionalEnv(key: string, defaultValue: string): string {
  return Bun.env[key] || defaultValue;
}

export const config = {
  // 必需的环境变量
  databaseUrl: getRequiredEnv("DATABASE_URL"),
  apiKey: getRequiredEnv("API_KEY"),
  
  // 可选的环境变量
  port: parseInt(getOptionalEnv("PORT", "3000")),
  debug: getOptionalEnv("DEBUG", "false") === "true",
  logLevel: getOptionalEnv("LOG_LEVEL", "info"),
};

console.log("配置加载成功:", config);

使用 Zod 验证

typescript
// config.ts
import { z } from "zod";

const envSchema = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
  APP_PORT: z.string().transform(Number).default("3000"),
  DATABASE_URL: z.string().url(),
  API_KEY: z.string().min(10),
  DEBUG: z.string().transform(v => v === "true").default("false"),
});

export const config = envSchema.parse(Bun.env);

// 类型推断
// config.NODE_ENV: "development" | "production" | "test"
// config.APP_PORT: number
// config.DEBUG: boolean

动态设置环境变量

在代码中设置

typescript
// 设置环境变量
Bun.env.NEW_VAR = "new value";
process.env.ANOTHER_VAR = "another value";

// 读取
console.log(Bun.env.NEW_VAR);      // "new value"
console.log(Bun.env.ANOTHER_VAR);  // "another value"

// 删除
delete Bun.env.NEW_VAR;
console.log(Bun.env.NEW_VAR);      // undefined

子进程环境变量

typescript
import { $ } from "bun";

// 传递环境变量给子进程
const result = await $`echo $MY_VAR`.env({
  MY_VAR: "Hello from parent"
}).text();

console.log(result);  // "Hello from parent"

安全最佳实践

敏感信息处理

typescript
// ❌ 不要这样做
console.log("API Key:", Bun.env.API_KEY);

// ✅ 安全的日志记录
console.log("API Key:", Bun.env.API_KEY ? "***已设置***" : "未设置");

// ✅ 使用掩码
function maskSensitive(value: string): string {
  if (!value || value.length < 8) return "***";
  return value.slice(0, 4) + "***" + value.slice(-4);
}

console.log("API Key:", maskSensitive(Bun.env.API_KEY || ""));

环境变量模板

创建 .env.example 作为模板:

bash
# .env.example - 提交到版本控制
# 复制此文件为 .env 并填写实际值

# 应用配置
APP_NAME=myapp
APP_PORT=3000

# 数据库配置(必需)
DATABASE_URL=postgresql://user:password@localhost:5432/dbname

# API 密钥(必需)
API_KEY=your-api-key-here

# 可选配置
DEBUG=false
LOG_LEVEL=info

密钥管理

typescript
// 对于生产环境,使用密钥管理服务
import { SecretsManager } from "@aws-sdk/client-secrets-manager";

async function loadSecrets() {
  if (Bun.env.NODE_ENV === "production") {
    const client = new SecretsManager({ region: "ap-northeast-1" });
    const response = await client.getSecretValue({ SecretId: "my-app/prod" });
    const secrets = JSON.parse(response.SecretString!);
    
    // 合并到环境变量
    Object.assign(Bun.env, secrets);
  }
}

await loadSecrets();

bunfig.toml 环境配置

toml
# bunfig.toml

[run]
# 指定环境文件
env-file = [".env", ".env.local"]

# 设置环境变量
[run.env]
NODE_ENV = "development"
LOG_LEVEL = "debug"

特殊环境变量

Bun 专用变量

变量名说明
BUN_INSTALLBun 安装目录
BUN_CONFIG_VERBOSE_FETCH打印 fetch 请求详情
BUN_CONFIG_MAX_HTTP_CONNECTIONS最大 HTTP 连接数
BUN_JSC_*JavaScriptCore 引擎选项

Node.js 兼容变量

变量名说明
NODE_ENV运行环境
NODE_PATH模块搜索路径
NODE_DEBUG调试模块

实际应用示例

完整配置管理

typescript
// src/config/index.ts
import { z } from "zod";

// 环境变量 Schema
const envSchema = z.object({
  // 应用
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
  APP_NAME: z.string().default("my-app"),
  APP_PORT: z.coerce.number().default(3000),
  
  // 数据库
  DATABASE_URL: z.string().url(),
  DATABASE_POOL_SIZE: z.coerce.number().default(10),
  
  // Redis
  REDIS_URL: z.string().url().optional(),
  
  // 认证
  JWT_SECRET: z.string().min(32),
  JWT_EXPIRES_IN: z.string().default("7d"),
  
  // 外部服务
  API_KEY: z.string().optional(),
  
  // 日志
  LOG_LEVEL: z.enum(["error", "warn", "info", "debug"]).default("info"),
  
  // 功能开关
  FEATURE_NEW_UI: z.coerce.boolean().default(false),
});

// 解析并导出
const parsed = envSchema.safeParse(Bun.env);

if (!parsed.success) {
  console.error("❌ 环境变量配置错误:");
  console.error(parsed.error.format());
  process.exit(1);
}

export const config = parsed.data;

// 派生配置
export const isDev = config.NODE_ENV === "development";
export const isProd = config.NODE_ENV === "production";
export const isTest = config.NODE_ENV === "test";

使用配置

typescript
// src/index.ts
import { config, isDev } from "./config";

const server = Bun.serve({
  port: config.APP_PORT,
  
  fetch(request) {
    if (isDev) {
      console.log("收到请求:", request.url);
    }
    
    return new Response(`Welcome to ${config.APP_NAME}!`);
  },
});

console.log(`${config.APP_NAME} 运行在端口 ${server.port}`);

小结

本章介绍了:

  • ✅ 自动加载 .env 文件
  • ✅ 访问环境变量的多种方式
  • ✅ 多环境配置管理
  • ✅ 环境变量语法和变量引用
  • ✅ 配置验证和类型安全
  • ✅ 安全最佳实践

下一步

继续阅读 文件操作 了解 Bun 的高性能文件处理能力。

本站内容仅供学习和研究使用。