首页 / Bun 入门教程 / 环境变量与配置

Bun 入门教程

环境变量与配置

本教程共 34 篇 · 第 7 篇 · 更新于 2026-08-06

Bun环境变量.envBun.envbunfig.toml配置

本节目标:

  • 理解 Bun 如何自动加载 .env 以及多份文件的优先级
  • 搞清楚 Bun.envimport.meta.envprocess.env 是同一份数据的不同名字
  • 会用变量展开、引号与 --env-file / --no-env-file 控制加载行为
  • bunfig.toml 管理项目级与全局配置(env、serve、install 等)

环境变量是配置程序最常用的手段:数据库密码、API Token、运行模式等都不该写死在代码里。Bun 在这块做了贴心的内置支持——你大概率不再需要 dotenv 这类包。这一节把机制讲透。

7.1 .env 自动加载与优先级

Bun 会自动读取当前目录下的 .env 系列文件,无需任何代码。按优先级从低到高(后者覆盖前者):

  • .env
  • .env.production / .env.development / .env.test(取决于 NODE_ENV 的值)
  • .env.local

举例:用 NODE_ENV=production 运行时,.env.production 会覆盖 .env 里的同名项;设了 NODE_ENV=development 就用 .env.development.env.local 排在最后,常被 git 忽略,用来放本机私有的覆盖值。

这样分层,你可以在仓库里提交一份通用的 .env,把环境专属值和敏感配置拆到别的文件里管理。

Warning

有一个例外:NODE_ENV=test.env.local 不会被加载。这是为了防止本机的私有覆盖污染测试环境,保证每次跑测试的环境一致。Next.js、Create React App 也是同样的约定。

# .env
FOO=hello
BAR=world
console.log(process.env.FOO); // "hello"

也可以在命令行直接设置变量:

# Linux / macOS
FOO=helloworld bun run dev

# Windows (CMD)
set FOO=helloworld && bun run dev

# Windows (PowerShell)
$env:FOO="helloworld"; bun run dev
Tip

跨平台写变量,推荐用 Bun Shell,免去分平台语法的麻烦:

bun exec 'FOO=helloworld bun run dev'

另外,在 Windows 上,package.json 脚本经 bun run 调用时会自动走 Bun Shell,所以脚本里写 "dev": "NODE_ENV=development bun --watch app.ts" 也是跨平台可用的。

也可以在代码里用 process.env.FOO = "hello" 赋值,效果等同于在运行时设置。

7.2 Bun.env / import.meta.envprocess.env 的别名

三者指向同一份数据,读哪个都一样:

process.env.API_TOKEN;   // "secret"
Bun.env.API_TOKEN;       // "secret"
import.meta.env.API_TOKEN; // "secret"

Bun.envimport.meta.env 只是更「Bun 风格」的写法,方便在不能用 process 的上下文里取变量。import.meta.env 还常用于前端代码,便于和 Vite 等工具的习惯保持一致。

想一次性打印所有环境变量:

bun --print process.env

下面给一个最小可运行的完整示例,把「文件 → 读取 → 输出」串起来:

# .env
APP_NAME=MyApp
PORT=8080
// main.ts
console.log("app =", Bun.env.APP_NAME);
console.log("port =", Number(Bun.env.PORT));
bun run main.ts
# app = MyApp
# port = 8080

注意:.env 里的所有值都是字符串,使用时按需用 Number() / Boolean() 转换。不要把 "0" 当成 falsy——它是长度为一的非空字符串,在 JavaScript 里是 truthy,直接用 if (Bun.env.PORT) 做布尔判断可能得出与预期相反的结果。

Note

当 Bun 以 node 模式被调用时(例如 bun --bunbunx --bun,或一个指向 Bun 的 node 软链接),.env自动加载会被关闭,以匹配 Node.js 的默认行为。这样像 Vite 的 loadEnv 这类自带 .env 解析逻辑的工具,才能正确选择对应模式的文件,而不被 Bun 预填的值干扰。如果你显式传了 --env-file,则仍然会加载。

7.3 变量展开、引号与转义

.env 里支持双引号、单引号与模板字符串反引号:

FOO='hello'
FOO="hello"
FOO=`hello`

Bun 会自动展开变量,可以引用前面定义过的变量,适合拼连接字符串:

FOO=world
BAR=hello$FOO
process.env.BAR; // "helloworld"

构造数据库连接串时很好用:

DB_USER=postgres
DB_PASSWORD=secret
DB_HOST=localhost
DB_PORT=5432
DB_URL=postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/app

若要原样保留 $ 而不展开,用反斜杠转义:

FOO=world
BAR=hello\$FOO
process.env.BAR; // "hello$FOO"
Note

因为 Bun 原生读取 .env,所以 dotenvdotenv-expand 在 Bun 项目里是多余的。如果你从 Node.js 老项目迁移并带了 require("dotenv").config(),它在 Bun 下不会出错,但通常可以删掉,让 Bun 的自动加载接管。

7.4 手动指定与禁用 .env 加载

--env-file 可以精确指定要加载哪个(或哪几个).env 文件,覆盖默认加载:

bun --env-file=.env.1 src/index.ts
bun --env-file=.env.abc --env-file=.env.def run build

--no-env-file关闭自动加载,只认系统环境变量。这在不希望任何 .env 影响结果的场景(如生产、CI/CD)很有用:

bun run --no-env-file index.ts
Warning

生产或 CI 环境里,如果敏感信息已经通过系统环境变量注入(如容器 secret、CI 变量),务必用 --no-env-filebunfig.toml 关掉 .env 自动加载,避免本地 .env 文件意外覆盖生产配置,或把开发用的假值带上线。注意:即便关掉默认加载,--env-file 显式指定的文件仍然会加载。

7.5 在 TypeScript 里获得类型提示

默认 process.env 上每个属性都是 string | undefined。想要自动补全、并让某个变量被当作必填字符串,可以用接口合并(declaration merging):

declare module "bun" {
  interface Env {
    AWESOME: string;
  }
}

把这个声明放进项目任意文件,全局就会给 process.env.AWESOMEBun.env.AWESOME 加上 string 类型。

7.6 用 bunfig.toml 做项目配置

bunfig.toml 是 Bun 专属的配置文件(可选,没有它 Bun 也能跑)。Bun 尽量复用 package.jsontsconfig.json 等既有文件,bunfig.toml 只放 Bun 特有的设置。放在项目根目录(与 package.json 同级)即生效;全局配置可放在 $HOME/.bunfig.toml$XDG_CONFIG_HOME/.bunfig.toml。若全局与本地都存在,则浅合并,本地优先;CLI 参数优先级最高。

最常用的几个字段:

关闭 .env 自动加载

# 关闭默认 .env 加载(生产 / CI 推荐)
env = false

也支持对象写法:

[env]
file = false

配置 HTTP 服务默认端口

[serve]
port = 3000

也可通过 BUN_PORT / PORT 环境变量或 --port 覆盖。

设置运行时日志级别

logLevel = "warn" # "debug" | "warn" | "error"

配置 JSX(非 TS 项目也能用)

jsx = "react"
jsxFactory = "h"
jsxImportSource = "react"

关闭遥测与崩溃报告

telemetry = false

等价于设置环境变量 DO_NOT_TRACK=1

指定预加载脚本

# 运行任何文件或脚本前先执行
preload = ["./preload.ts"]
Tip

还有大量 [install][test][run] 子配置可写进 bunfig.toml,例如指定私有 registry、锁文件冻结(frozenLockfile)、测试覆盖率阈值、把 node 透明替换成 bunrun.bun = true)等。它们属于包管理器与测试章节的内容,这里先知道「bunfig.toml 是统一配置入口」即可,用到再查对应章节。

举两个会在后续章节深入、但此处可先建立印象的例子:

# CI 里锁定依赖版本,不更新 bun.lock
[install]
frozenLockfile = true

# 让 bun run 起的服务默认走 Bun(node 透明替换)
[run]
bun = true

优先级始终是:CLI 参数 > 本地 bunfig.toml > 全局 .bunfig.toml。因此团队成员可以把个人偏好放全局配置,项目统一约束放本地配置,命令行临时覆盖,三者各司其职、互不打架。

7.7 几个有用的 Bun 专属环境变量

除了读你自己的变量,Bun 也认一些控制自身行为的变量:

变量作用
NODE_TLS_REJECT_UNAUTHORIZED=0关闭 SSL 证书校验,仅调试用,生产慎用
BUN_CONFIG_VERBOSE_FETCH=curlfetch 请求的 URL / 头打印成 curl 形式,便于调试
BUN_CONFIG_MAX_HTTP_REQUESTSfetchbun install 的最大并发请求数,默认 256
BUN_OPTIONS="--hot"给任意 Bun 执行追加 CLI 参数,等价于默认带上 --hot
DO_NOT_TRACK=1关闭崩溃报告与遥测上传
NO_COLOR=1 / FORCE_COLOR=1控制是否输出 ANSI 颜色

例如想让所有 bun run 默认带热重载:

BUN_OPTIONS="--hot" bun run dev

7.8 小结

  • Bun 自动加载 .env 系列文件,优先级:.env < .env.{mode} < .env.localNODE_ENV=test 时不加载 .env.local
  • Bun.envimport.meta.envprocess.env 是同一份数据的三个名字。
  • 变量支持引号与 $展开\$ 转义可阻止展开。原生支持让你无需 dotenv
  • --env-file 指定文件,--no-env-file 关闭自动加载(生产 / CI 推荐)。
  • bunfig.toml 是 Bun 专属配置入口,可关 .env、设端口、配 JSX、管 install/test/run;本地覆盖全局,CLI 覆盖配置。
Note

配置这件事,「显式优于隐式」。在团队项目里,建议把 .env.local 放进 .gitignore,只提交 .env.example 作为模板;生产变量走系统环境变量并配合 --no-env-file,这样配置来源清晰、不易出错。同时记住:.env 不会被 Bun 自动提交到任何地方,但本地明文密码仍要当心,分享机器或做容器镜像前先确认没有把含密钥的 .env 一并打进去。