关于 bun-cli
bun-cli 是面向 Bun 项目开发者的命令行技能,汇总运行时、包管理、构建、测试、类型检查和格式化用法。它强调依据已安装版本核对功能与文档,并在 Bun 项目中统一使用 Bun 命令。
主要功能
- 01运行 JavaScript 和 TypeScript
- 02管理依赖与工作区
- 03打包、测试与类型检查
- 04格式化代码
- 05按版本核对命令和行为
适用场景
- 01在 Bun 项目中运行脚本和测试
- 02安装、更新或审计依赖
- 03排查版本升级带来的行为变化
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dmythro/ agent-skills --skill bun-cli安装后在 Claude Code 中输入/bun-cli确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/allowlist.mdbundling-and-compilation.mdconfiguration.mdformatting.mdmigration-1.4.mdpackage-management.mdrunning-and-execution.mdtesting.mdtype-checking.md详细介绍
Bun CLI
Bun 是一体化的 JavaScript/TypeScript 运行时、包管理器、打包器、测试运行器、类型检查器(v1.4.3+)和格式化工具(v1.4.4+)。Bun 可原生运行 TypeScript——直接执行 bun file.ts,无需编译步骤,也无需 tsc 或 ts-node;bun check 可替代 tsc --noEmit,bun fmt 可替代 prettier --write。在 Bun 项目中,始终使用 bun,不要使用 node、npm、npx、yarn 或 pnpm。
已针对 Bun v1.4.4 验证(2026-10-22)。功能标注了其引入版本(v1.4+、v1.4.1+、v1.4.2+、v1.4.3+、v1.4.4+)。如果某个版本更改了现有行为,会同时说明新旧行为,以确保本指南在较旧项目中仍然适用——使用带版本标注的功能前,先运行 bun --version。
版本指南:各个 1.4.x 版本的更改
| 版本 | 新增功能 | 现有项目中的更改 | 适合升级的情况 |
|---|---|---|---|
| 1.4.0(2026-08-20) | bun audit fix、bun dedupe、bun prune、bun why、bun pm licenses / diff、add / remove / update 上的 --filter、--catalog、bun test --timings、--react-compiler、--asset | bun.lock v2 / v3(Bun 1.3 无法读取 v3)、严格 TOML 格式的 bunfig.toml、bun update 会移动传递依赖、resetAllMocks() 会丢弃实现 | 你需要 1.4 工具链时——先检查每个 CI 中固定的 Bun 版本及 bunfig.toml |
| 1.4.1(2026-09-04) | --offline / --prefer-offline、自包含工作区、--min-chunk-size、--bytecode-depth、从管道读取的 --env-file、--no-ffi-cc | 拆分后的代码块更少且体积更小,并增加 modulepreload 链接(构建快照会变化) | 不要选择此版本作为目标:其打包器可能会把嵌套的 var 重命名为 let,导致 Elysia 包无法加载——请升级到 1.4.2 或更高版本 |
| 1.4.2(2026-09-05) | 无(错误修复版本) | -- | 你正在使用 1.4.1,或者 bun install 因 range end index out of range 而崩溃 |
| 1.4.3(2026-10-10) | bun check / --check、--bytecode-order、--compile-jit-policy、[hash9]-[hash13] | 安装时只缓存实际放置的内容(--offline 缓存需要先完整预热一次安装),强制执行 --disallow-code-generation-from-strings、遵循 Bun.build({ tsconfig })、--coverage-reporter 会隐含启用 --coverage | 你想要无需 tsc 的类型检查,或者大型 --splitting 构建因 Multiple files share the same output path 而失败 |
| 1.4.4(2026-10-22) | bun fmt、bun pm fetch、bun pm cache pack / unpack / prune、bun publish --recursive、packageExtensions、link:./path、--libc、bun check --no-script、Yarn Berry 锁文件迁移 | 未知的包管理器标志会以状态码 1 退出,npm/Yarn/pnpm 标志会被转换;采用 pnpm 风格的 peer 依赖解析;覆盖率统计更严格;hoisted 链接器会移除从 package.json 中删除的依赖 | 你需要内置格式化工具、Berry 迁移、可在注册表短暂中断后继续的 bun install 重试,或修复 133 个已关闭的 bun install 问题——运行一次 CI,检查标志错误和 coverageThreshold 降低的情况 |
默认选择最新的补丁版本。 每个补丁版本都会修复此前版本中的回归问题(按版本列于
references/migration-1.4.md),因此固定在较旧的“已知良好”1.4.x 版本会保留已知缺陷。
升级项目之前,请阅读期间每个版本的“现有项目中的更改”列:升级可能需要进行这些修改。
查看版本,再查阅 Bun 文档
bun <command> --help 是参数的权威来源,且始终与已安装的二进制文件保持一致。如果这里的表格与之不符,应优先以它为准。
对于参数以外的所有内容,Bun 会通过 bun-types 附带与运行时版本匹配的完整文档。任何安装了 bun-types 或 @types/bun 的项目都可以使用这些文档:
node_modules/bun-types/docs/pm/**/*.mdx # install, lockfile, workspaces, catalogs, linkers
node_modules/bun-types/docs/test/**/*.mdx # test runner
node_modules/bun-types/docs/bundler/**/*.mdx # bun build, executables, loaders, plugins
node_modules/bun-types/docs/runtime/bunfig.mdx
node_modules/bun-types/CLAUDE.md # Bun's own agent rules
-
依赖
bun-types,而不是@types/bun。 每个 Bun 版本都附带bun-types,其中包含文档和类型。@types/bun总是落后于每个版本,通常会晚一天或更久;但bun init会将其添加为latest,因此bun check会拒绝最新的 API(TS2339、TS2353)。在@types/bun旁边添加bun-types只能修复文档路径:类型检查仍会使用@types/bun嵌套的固定版本副本。请同时切换两者:bun remove @types/bun bun add -d bun-types@$(bun --version) # then "types": ["bun-types"] in tsconfig.json
在信任任一版本之前,请比较 bun --version 和 node_modules/bun-types/package.json 中的版本。
2. 通过明确路径打开。 启用全局虚拟存储后,node_modules/bun-types 是符号链接,因此 find node_modules -name '*.mdx' 和 rg <pattern> node_modules 都不会返回任何结果。find node_modules/bun-types/docs -name '*.mdx' 可以正常工作。
3. 切勿编辑 node_modules/ 下的文件。 在全局存储下,机器上的所有项目共享同一个 inode。请使用 bun patch。
4. 尚未安装? 同一路径也适用于在线文档:docs/pm/lockfile.mdx 对应 https://bun.com/docs/pm/lockfile。
5. 文档可能领先于正式版本。 bun-types 1.4.4 附带 docs/lint/** 和 runtime/bunfig.mdx 中的 [lint] 部分,但 bun lint 仅存在于 canary 构建中:稳定版 1.4.4 会将 bun lint 视为 bun run lint,因此会运行项目的 lint 脚本,或因 Script not found "lint" 而失败。请保留项目的 linter。
| 任务 | 文档路径(位于 node_modules/bun-types/docs/ 下) |
|---|---|
| 安装行为、锁文件、链接器 | pm/cli/install.mdx、pm/lockfile.mdx、pm/isolated-installs.mdx、pm/global-store.mdx |
| 工作区、目录、过滤器、覆盖项 | pm/workspaces.mdx、pm/catalogs.mdx、pm/filter.mdx、pm/overrides.mdx、pm/package-extensions.mdx(v1.4.4+) |
| 注册表、身份验证、生命周期脚本 | pm/scopes-registries.mdx、pm/npmrc.mdx、pm/lifecycle.mdx |
类型检查(bun check、--check) | runtime/check.mdx |
格式化(bun fmt,v1.4.4+) | format/index.mdx、guides/format/migrate-from-prettier.mdx、guides/format/migrate-from-oxfmt.mdx |
| 测试运行器 | test/index.mdx、test/discovery.mdx、test/configuration.mdx、test/code-coverage.mdx、test/reporters.mdx、test/mocks.mdx |
| 打包器、可执行文件、加载器 | bundler/index.mdx、bundler/executables.mdx、bundler/loaders.mdx、bundler/plugins.mdx |
| 配置 | runtime/bunfig.mdx |
| 从 npm/yarn/pnpm 迁移 | guides/install/from-npm-install-to-bun-install.mdx |
检测 Bun 项目
出现以下任一情况,即表示项目使用 Bun:
- 项目根目录中有
bun.lock或bun.lockb - 项目根目录中有
bunfig.toml package.json中有bun字段(例如"bun": { "install": { ... } })- 包管理器字段:
"packageManager": "bun@..." bunfig.toml中有[run] bun = true(强制所有脚本使用 Bun 运行时)
关键规则
在 Bun 项目中,所有操作始终使用 bun。 切勿回退到 node、npm、npx、yarn 或 pnpm。这样可以避免兼容性问题、不必要的重试,以及 Node.js/npm 无法理解 Bun 专属功能(工作区协议、锁文件格式、trustedDependencies 等)而产生的晦涩错误。
- 运行文件:
bun file.ts(而不是node file.ts) - 运行脚本:
bun run dev(而不是npm run dev) - 执行二进制文件:
bunx tool(而不是npx tool) - 安装软件包:
bun add pkg(而不是npm install pkg) - 运行测试:
bun test(而不是npx jest或node --test) - 类型检查:
bun check(而不是tsc --noEmit;v1.4.3+) - 格式化:
bun fmt(而不是prettier --write .;v1.4.4+)
只读命令(安全,无副作用)
| 命令 | 用途 |
|---|---|
bun --version | 运行时版本 |
bun info <pkg> | 包元数据、可用版本 |
bun info <pkg> versions | 列出所有已发布版本 |
bun pm ls | 列出已安装的包(别名:bun list) |
bun pm ls --all | 列出所有包(包括传递依赖) |
bun pm ls --trusted | 仅列出允许运行生命周期脚本的包(v1.4+) |
bun pm ls <name> | 列出某个包的所有已安装副本(v1.4.4+) |
bun pm hash | 输出锁文件哈希 |
bun pm cache | 显示缓存目录 |
bun pm bin | 输出 bin 目录(全局模式使用 -g) |
bun pm licenses | 按许可证分组列出依赖(v1.4+;--json、--prod) |
bun pm diff <pkg> | 对比某个包的两个版本(v1.4+) |
bun pm untrusted | 列出生命周期脚本被阻止的包 |
bun why <pkg> | 说明安装某个包的原因 |
bun outdated | 检查过时的依赖 |
bun audit | 安全漏洞审计 |
bun dedupe --check | 如果锁文件中存在可移除的重复项,则退出码为 1(v1.4+) |
bun prune --dry-run | 显示将从 node_modules 中移除的内容(v1.4+) |
bun prune --check | 如果 node_modules 中存在可移除的包,则退出码为 1;不会删除任何内容(v1.4.4+) |
bun install --frozen-lockfile --dry-run | 如果 bun.lock 与 package.json 不一致,则退出码为 1;不会安装任何内容。在 v1.4.4 之前,--dry-run 仍会运行项目的生命周期脚本 |
bun test | 运行测试套件 |
bun --check | 检查整个项目的类型后退出;绝不会写入文件或运行脚本(v1.4.3+)。除非 package.json 定义了 check 脚本(此时会运行该脚本),否则 bun check 的行为相同;bun check --no-script(v1.4.4+)绝不会运行该脚本 |
bun fmt --no-script --check | 列出需要格式化的文件;如有任何文件,则退出码为 1;不会写入任何内容(v1.4.4+)。如果不加 --no-script,则会改为运行 package.json 中的 fmt 脚本 |
bun run lint | 运行代码检查工具(依项目而定) |
bun run check-types | 类型检查(依项目而定) |
参考:请参阅
references/allowlist.md,获取适用于 Claude Code / OpenCode 设置的可直接复制粘贴的Bash(command:*)模式。
npm/npx/node 到 Bun 的转换
| npm/npx/node | Bun 对应命令 |
|---|---|
npm install | bun install |
npm install pkg | bun add pkg |
npm install -D pkg | bun add -d pkg |
npm install -g pkg | bun add -g pkg |
npm uninstall pkg | bun remove pkg |
npm update | bun update |
npm run script | bun run script |
npx command | bunx command |
node file.js | bun file.js |
node --watch file.js | bun --watch file.js |
npm test | bun test |
tsc --noEmit | bun check(v1.4.3+) |
prettier --write . | bun fmt --no-script(v1.4.4+;如果 package.json 中有 fmt 脚本,直接运行 bun fmt 会执行该脚本) |
prettier --check . | bun fmt --no-script --check(v1.4.4+) |
npm pack | bun pm pack |
npm publish | bun publish |
npm info pkg | bun info pkg |
npm outdated | bun outdated |
npm audit | bun audit |
npm link | bun link |
关键行为差异
- 无需添加
npm run前缀:bun run dev可以运行,bun dev也可以(直接执行脚本) --bun标志:对于 shebang 中使用node的脚本,强制使用 Bun 运行时而非 Node.js。在bunfig.toml中设置[run] bun = true可将其设为默认值- 锁文件:Bun 使用
bun.lock(文本格式,v1.2+)或bun.lockb(二进制格式,旧版)。新项目默认使用文本锁文件 - 工作区命令:使用
--filter标志:bun --filter 'pkg-name' add dep - 生命周期脚本:出于安全考虑,Bun 默认忽略生命周期脚本。使用 package.json 中的
trustedDependencies将需要执行 postinstall 等脚本的包加入允许列表 - 其他包管理器的标志(v1.4.4+):
install、ci、add、remove和update会转换为 Bun 有对应项的 npm/Yarn/pnpm 标志(--save-dev、--immutable、--shamefully-hoist、--only=production),跳过不受支持的标志及其值(--network-timeout 100000),并在遇到任何包管理器都不支持的标志时以状态码 1 退出,包括拼写错误(--frozen-lockfil)。Bun 1.4.3 在这三种情况下都处理错误:bun add --save-dev x将依赖写入了dependencies,--network-timeout 100000尝试安装名为100000的包,而拼写错误的标志则执行了普通安装
包管理
安装依赖
bun install # Install all from package.json
bun install --frozen-lockfile # CI mode: fail if lockfile needs update
bun install --no-save # Install without updating package.json
bun install --production # Skip devDependencies
bun install --dry-run # Show what would be installed; runs no scripts as of v1.4.4
bun install --offline # No network at all; every package must already be cached (v1.4.1+)
bun install --prefer-offline # Cached metadata regardless of age; download only what is missing (v1.4.1+)
bun install --env-file ci.env # Env for lifecycle scripts; every package manager command takes it (v1.4.4+)
bun install --libc musl # Native packages for another libc, e.g. an Alpine image from glibc (v1.4.4+)
bun pm fetch # Download every locked package into the cache; no node_modules, no scripts (v1.4.4+)
--offline 适合会恢复 ~/.bun/install/cache 的 CI 作业,以及无法联网的机器——缺少的包会按名称报错(no cached manifest for 'left-pad')。--prefer-offline 会跳过新鲜度检查,但仍会获取缓存中没有的包。两者也有对应的 bunfig.toml 设置:[install] offline = true 和 [install] prefer = "offline"。
1.4.3 中的变更——安装只缓存实际放入的内容。 没有锁文件时,bun install 和 bun add 不再下载不会进入 node_modules 的 tarball:被 --production 或 --omit 排除的依赖组、其他平台的可选包、捆绑依赖。使用 bun install --production 预热的缓存,之后执行完整的 --offline 安装会失败,并提示 "left-pad" is not in the cache。预热离线缓存时,应使用至少会放入相同包的安装命令,并在相同平台上执行。
1.4.4 中的变更——解析。 对等依赖的解析方式与 pnpm 相同:如果上级目录中没有任何包提供某个包的对等依赖,就会为其选择一个符合对等依赖版本范围的版本,并由所有具有该对等依赖的包共享。Bun 1.4.3 会将其他无关包安装的版本交给它——例如,与 @modelcontextprotocol/sdk(express@5)并存时,@remix-run/express 得到的是不符合其 ^4.20.0 对等依赖要求的 express@5;1.4.4 则会为它嵌套安装 express@4。bun.lock 中已有的版本会保留;移除并重新添加包,才能重新解析其对等依赖。其他新增内容:Yarn Berry 的 yarn.lock 文件可迁移为 bun.lock,并保留所有锁定版本(1.4.3 仅支持迁移 Yarn v1);Linux 安装会跳过为其他 libc 构建的可选原生包(--libc '*' 会安装两者);注册表请求失败时会从 50 ms 起按指数退避重试(对于持续约 1.5 s 以上的故障,可设置 BUN_CONFIG_HTTP_RETRY_BACKOFF=250)(发布说明)。
添加/移除包
bun add pkg # Add to dependencies
bun add pkg@version # Add specific version
bun add -d pkg # Add to devDependencies (--dev)
bun add -D pkg # Same as -d
bun add --optional pkg # Add to optionalDependencies
bun add --peer pkg # Add to peerDependencies
bun add -g pkg # Install globally
bun add --exact pkg # Pin exact version (no ^)
bun add pkg --filter api # Add to one workspace from the repo root (v1.4+)
bun add pkg --catalog # Add to the root catalog, depend on it as "catalog:" (v1.4+)
bun add --save-prod pkg # Move back to dependencies from another group (v1.4.4+)
bun remove pkg # Remove package
1.4.4 中的变更: 如果某个包已列在其他依赖组中,bun add -d、--optional、--peer 和 --save-prod 会将其移至相应依赖组(此前它仍留在原处);--exact 会锁定已安装的版本(is-number@7 会写入 7.0.0,而非 7);直接依赖已弃用时会打印 warn: deprecated <pkg>@<version>: <message>。根据发布说明,解析也会像 npm 一样优先选择未弃用的版本。
1.4 中的变更: bun add、bun remove 和 bun update 支持 --filter;bun install <pkg> --filter x 现在会修改工作区 x,而不是根目录。在默认目录中已列出该包的工作区里,直接运行 bun add <pkg> 会写入 catalog:。--filter 'web...' 会选择 web 及其所有依赖项;'...web' 会选择所有依赖 web 的包。
更新与检查
bun update # Update all packages within package.json ranges
bun update pkg # Update every copy of pkg, transitive ones included (v1.4+)
bun update '@types/*' --latest # Patterns; --latest ignores the declared range
bun update --recursive # Update every workspace and write each package.json (v1.4+)
bun update --filter 'pkg-*' --filter '!pkg-c' # Repeatable; ! excludes (v1.4+)
bun update --depth 0 # Direct dependencies only; transitive ones stay locked unless a new range excludes them (v1.4.4+)
bun outdated # Show outdated packages
bun info pkg # Show package metadata
bun info pkg versions # List all available versions
bun info pkg version license # Several properties at once, npm view paths too (v1.4.4+)
bun why pkg # Explain why a package is in the tree
bun pm ls # List installed packages (alias: bun list)
bun pm ls react # Every installed copy of react (v1.4.4+)
bun pm ls --all # List all (including transitive)
bun pm hash # Print lockfile hash
bun pm cache # Show cache directory
bun pm cache rm # Clear cache (including the global virtual store)
1.4 版本变更:bun update 会重新解析传递依赖,而不只是 package.json 中列出的依赖;如果没有任何依赖项依赖指定名称,bun update <name> 会以退出码 1 报错(以前会添加该包)。
维护(v1.4+)
bun audit fix # Upgrade vulnerable packages to the lowest safe version
bun audit fix --dry-run # Preview
bun audit fix --latest # Also apply fixes your declared ranges exclude
bun audit --prod # Skip packages only devDependencies need; --omit dev|optional|peer (v1.4.4+)
bun dedupe # Collapse duplicate versions in bun.lock, then install
bun dedupe --check # CI gate: exit 1 if duplicates remain
bun prune # Drop node_modules entries no longer in bun.lock
bun prune --production # Also drop devDependencies -- build with them, ship without
bun prune --check # CI gate: exit 1 if anything is removable, delete nothing (v1.4.4+)
bun pm licenses --prod --json # License inventory
bun pm diff [email protected] 19.0.0 # What changed between two versions of a package
bun pm cache prune --dry-run # Cached packages older than 30 days; --max-age <days> (v1.4.4+)
bun pm diff 会先显示摘要——已更改的文件、新增的安装脚本,以及新增的 child_process、fs、net 或 vm 导入——然后显示差异,并展开压缩文件、跳过仅涉及格式的更改。适合用于审查依赖项升级。
bun prune --production 适用于 Docker 构建阶段:
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
RUN bun prune --production
CI 缓存与 Docker 层(v1.4.4+)
bun pm fetch 会将 bun.lock 锁定的所有包下载到缓存中,不做其他操作——不创建 node_modules、不运行脚本、不写入锁文件——因此只有在 package.json 或 bun.lock 发生变化时才会重新构建下载层:
COPY package.json bun.lock ./
RUN bun pm fetch
COPY . .
RUN bun install --offline --frozen-lockfile
在 monorepo 中,这两个根目录文件涵盖所有工作区,但以下例外也必须复制到该层:bunfig.toml / .npmrc 中的注册表设置(缓存条目按注册表主机名区分,因此缺少这些设置时,安装会重新下载所有内容)、锁文件中指定的补丁文件和本地 tarball,以及根 package.json 使用 workspace: 依赖的任何工作区。
**切勿将注册表令牌放入镜像。**复制包含明文 _authToken 的 .npmrc 会使令牌留在构建层和构建缓存中。在 .npmrc 中将令牌写为 ${NPM_TOKEN}(在 bunfig.toml 中写为 $NPM_TOKEN),并将其值作为构建密钥传入(BuildKit,Dockerfile 语法 1.10+):
COPY package.json bun.lock .npmrc ./ # .npmrc: //npm.pkg.github.com/:_authToken=${NPM_TOKEN}
RUN --mount=type=secret,id=npm_token,env=NPM_TOKEN bun pm fetch
bun pm cache pack <file> 会将锁文件所需的缓存条目写入一个文件;bun pm cache unpack <file> 会在另一个运行器上恢复这些条目,只添加缺少的内容:
bun pm cache pack .ci/bun-cache.pack # after an install
bun pm cache unpack .ci/bun-cache.pack # next job, before bun install --frozen-lockfile
链接与补丁
bun link # Register current package as linkable
bun link pkg-name # Link a registered package into node_modules; package.json is untouched
bun link --save pkg-name # Also add "pkg-name": "link:pkg-name" to package.json
bun pm pack # Create tarball of package
bun patch pkg # Start patching a package
bun patch --commit pkg-dir # Apply patch
从 v1.4.4 起,link: 接受路径("tokens": "link:./vendor/tokens"),该路径相对于声明它的 package.json:Bun 会对目录创建符号链接,无需先运行 bun link。该目录自身的依赖项不会安装——如需安装,请使用 file: 或工作区——而且已发布的包不得声明此类依赖。没有路径的 link:name 仍表示通过 bun link 注册的包。Bun 1.4.3 会因这类路径报错,提示 failed to resolve。
发布
bun publish # Publish to npm
bun publish --dry-run # Preview what would be published
bun publish --tag beta # Publish with tag
bun publish --access public # Set access level
bun publish --recursive # Every workspace not on the registry yet, dependencies first (v1.4.4+)
bun publish --filter '@acme/*' # Only the matching workspaces (v1.4.4+)
--recursive 会在发布第一个包之前打包所有包,并跳过私有包;根据发布说明,它也会跳过注册表中已有的版本,因此失败后重新运行是安全的。**1.4.4 版本变更:**像 2.0.0-beta.1 这样的预发布版本必须指定 --tag 或 publishConfig.tag——bun publish 会以 prerelease needs a tag 报错,而不是像 npm 11 那样将其标记为 latest;publishConfig.registry 则用于设置发布位置(发布说明)。
未声明的依赖项:packageExtensions(v1.4.4+)
在隔离链接器下,导入未声明依赖项的包会失败。请直接在根目录的 package.json 中补上缺少的条目,而不是修补或分叉该包——格式与 pnpm/Yarn 相同,Bun 在迁移它们的锁文件时会复制此格式:
{
"packageExtensions": {
"legacy-plugin@2": { "dependencies": { "lodash": "^4.17.21" } },
"react-redux@7": { "peerDependencies": { "react": "*" } }
}
}
**参考:**完整的标志说明请参见
references/package-management.md。
安装布局:链接器与全局虚拟存储
两个设置决定了 node_modules 的布局。它们的重要性超乎表面看起来。
链接器
hoisted | isolated | |
|---|---|---|
| 布局 | npm 风格的扁平 node_modules | 链接到 node_modules/.bun/ 的符号链接(pnpm 风格) |
| 幽灵依赖 | 静默解析 | 解析失败,这是应有的行为 |
| 默认情况 | configVersion = 0(任何项目),或不使用工作区的 configVersion = 1 | configVersion = 1 且项目使用工作区 |
默认值取决于锁文件的 configVersion,而不是 Bun 版本:仅当 configVersion = 1 且项目使用工作区时,才使用 isolated。v1.3.2 之前创建的锁文件会被视为 configVersion = 0,并保持 hoisted,因此升级 Bun 不会改变现有项目的布局。可使用 --linker 或 [install] linker 覆盖。
全局虚拟存储(v1.3.14+,在 1.4 中更快)
软件包文件只存放一份于 ~/.bun/install/cache/links/ 中,每个项目都通过符号链接指向它们:
热安装速度约快 7 倍,node_modules 也会从数百 MB 缩减到几 MB 的链接。此功能默认关闭,且需要同时设置两个选项——当 linker = "hoisted" 时,globalStore 标志会被静默忽略。
[install]
linker = "isolated" # prerequisite
globalStore = true
BUN_INSTALL_GLOBAL_STORE=1 bun install --linker isolated # per invocation
bun pm cache rm # clears the store too
启用前值得了解的影响:
node_modules中大多是符号链接。find node_modules -name '*.mdx'和rg <pattern> node_modules都不会返回结果,而du -sh node_modules会报告约0B, 因为它统计的是符号链接,而非其目标(实际目录树由几 MB 的链接组成;du -sh -L会显示目标大小,并对每个链接分别计数)。通过明确路径访问文件,或传入find -L(它会通过链接层重复计数)。 不跟随符号链接扫描node_modules的工具会表现不同——这与任何 pnpm 风格布局的注意事项相同。- 每个项目共享相同的 inode。 编辑
node_modules/下的文件会影响此计算机上的所有项目。请使用bun patch。 - 真正的幽灵依赖将无法解析。 软件包的真实路径会指向缓存,因此隐藏的
node_modules/.bun/node_modules/层不再处于软件包内部的解析路径上。可通过声明依赖修复,或设置globalStore = false。 - 某些条目仍保留在项目本地:已修补的软件包、
trustedDependencies,以及任何依赖workspace:、file:或link:依赖项的内容。不符合条件的情况会沿依赖图向上传播,因此无论如何,单体仓库仍有相当一部分目录树会保留在本地。
参考:
node_modules/bun-types/docs/pm/global-store.mdx和pm/isolated-installs.mdx。
自包含工作区(v1.4.1+,hoisted 链接器)
Electron 打包器和无服务器打包器会重新打包某个工作区的 node_modules,并要求其所有依赖项都实际位于该工作区之下。请在根目录的 package.json 中列出此类工作区,或在工作区自己的文件中设置 Yarn 的 "installConfig": { "hoistingLimits": "workspaces" }:
{ "workspaces": { "packages": ["apps/*", "packages/*"], "selfContained": ["apps/desktop"] } }
该工作区直接或间接依赖的任何内容都不会被提升到 apps/desktop/node_modules 之上,而且这些软件包是实际副本,而不是缓存硬链接。
锁文件不会记录此设置,且它在 isolated 链接器下不起作用。
运行脚本和文件
直接执行
bun file.ts # Run TypeScript/JavaScript directly
bun run script-name # Run package.json script
bun script-name # Short form (if no conflict with bun commands)
bun --watch file.ts # Re-run on file changes
bun --hot file.ts # Hot reload (preserves state)
bun --env-file .env file.ts # Load env file
bun --env-file .env.local --env-file .env file.ts # Multiple env files
bun --no-env-file file.ts # Skip automatic .env loading (CI/prod; `env = false` in bunfig)
bun --env-file=<(op inject -i .env.tpl) file.ts # 1Password CLI renders dotenv lines; any pipe/FIFO//dev/stdin works (v1.4.1+)
bun --no-ffi-cc file.ts # cc() from bun:ffi throws ERR_FFI_CC_DISABLED (v1.4.1+)
bun --check file.ts # Type check the file and its imports first; nothing runs on an error (v1.4.3+)
bun --disallow-code-generation-from-strings=strict server.ts # eval/new Function/node:vm/data: imports throw EvalError (v1.4.3+)
bun --no-orphans run dev # Die with the parent, SIGKILL every descendant on exit
bun repl # Native REPL: highlighting, history, completion (v1.3.10+)
bun repl -p '{ a: 1 }' # Evaluate and print with REPL semantics
bun exec 'ls | wc -l' # Run a shell script through Bun's shell
bun ./README.md # Render Markdown in the terminal, no VM started
bunx(npx 的替代品)
bunx command # Run package binary (auto-installs if needed)
bunx --bun command # Force Bun runtime for the command
bunx command@version # Run specific version
bunx --cwd packages/api --env-file ci.env prisma migrate deploy # Another directory, an env file (v1.4.4+)
从 v1.4.4 起,bunx 遇到自身不支持的标志时会以状态码 1 退出(bunx has no --x flag. Flags for the package go after its name.);1.4.3 会忽略该标志并运行工具。
并行和顺序执行
替代 npm-run-all 和 concurrently。输出会按脚本添加前缀(使用 --filter 时为
package:script),并且 pre*/post* 钩子会与主脚本保持分组。
bun run --parallel build lint typecheck # Run all concurrently
bun run --parallel 'build:*' # Glob-match script names
bun run --parallel --filter '*' build # Fan out across every workspace
bun run --parallel --no-exit-on-error --filter '*' test # Keep going past failures
bun run --sequential clean build deploy # One at a time, same prefixed output
该标志也可以放在 run 前面(bun --parallel run build lint);两种形式都有效。
工作区感知执行
bun --filter 'pkg-name' run script # Run in specific workspace
bun --filter '*' run script # Run in all workspaces
bun --filter './apps/*' run build # Run with glob pattern
脚本标志
bun run --smol file.ts # Reduce memory usage (sacrifice throughput)
bun run --silent script # Suppress script name echo
bun run --shell=bun script # Use Bun's built-in shell (cross-platform, default on Windows)
bun run --shell=system script # Use system shell (default on macOS/Linux)
零配置前端开发
直接将 HTML 文件作为开发服务器运行——无需 Vite、Webpack 或任何配置:
bun ./index.html # Start dev server, auto-bundles JS/TS/CSS
bun --hot ./index.html # With hot module replacement
Bun 会自动转译 TypeScript、JSX、TSX,以及从 HTML 链接的 CSS。在 <script> 标签中解析 node_modules 导入。启用 HMR 和 React Fast Refresh。
从 v1.4.4 起,--port 3000 和 --host 0.0.0.0 可以用空格分隔;Bun 1.4.3 会忽略这些参数,除非写成 --port=3000,并且无论如何都会在 3000 端口上提供服务。
参考:完整详情请参阅
references/running-and-execution.md。
类型检查(v1.4.3+)
bun check 是内置的 TypeScript 7 移植版本:它读取 tsconfig.json,报告 tsc 报告的问题,使用所有 CPU 核心,无需安装 typescript 包,也不会写入文件。发现任何错误时退出码为 1;检查通过时为 0;没有可检查内容时也为 1。
bun check # the project of the nearest tsconfig.json
bun check src/index.ts # one file and everything it imports
bun check -b # every project in `references`, like tsc -b -- nothing pre-built
bun check --no-script # the type checker even when package.json has a "check" script (v1.4.4+)
bun --check src/index.ts # type check, then run; nothing runs on an error
bun test --check # no test runs on an error
bun build --check ./app.ts --outdir dist # nothing is written on an error
bun --watch --check src/index.ts # re-check before every restart (there is no bun check --watch)
- 将
types指向bun-types。 如果没有 Bun 类型,或@types/bun版本过旧,Bun、bun:test以及所有比已安装类型更新的 API 都无法通过检查。参见上文的“检查版本”。 check脚本优先。 如果package.json定义了check,bun check就会运行该脚本——无论是从 shell 还是从其他脚本调用都是如此。因此,bun init生成的"typecheck": "bun check"会运行 lint 脚本,传入的标志也会传给它。只有在check脚本及其启动的脚本中,bun check才是类型检查器。bun --check和bun check --no-script(v1.4.4+)始终执行类型检查;在脚本和 CI 中请使用其中一个。在 1.4.3 中,--no-script不是有效标志——check脚本会运行并接收该参数——因此 Bun 版本不固定时,优先使用bun --check。在较旧版本的 Bun 上,"check": "bun check"会无限递归调用自身。- Agent 输出。 设置
CLAUDECODE=1、AGENT=1或REPL_ID=1后,错误会以<error file= line= column= code=>块的形式打印,并附带源代码行。--no-pretty会为每个错误输出一行file(line,col): error TSxxxx: ...;通过管道传输时这是默认行为;摘要会输出到 stderr。 - 无论安装了哪个版本的
typescript,都遵循 TypeScript 7 规则:strict默认开启,除非明确列出,否则types为空;已移除的选项(baseUrl、moduleResolution: "node"、target: "es5")会导致检查在检查任何文件之前停止。 - 生成
.d.ts文件仍需使用tsc——bun check不会生成任何内容。
参考:关于
--check的检查范围、输出格式、单体仓库、CI,以及 TypeScript 5 到 7 的迁移表,请参阅references/type-checking.md。
格式化(v1.4.4+)
bun fmt 是内置于 Bun 的 Prettier 兼容格式化工具:支持 JavaScript、TypeScript、CSS、HTML、JSON、YAML、Markdown 等格式,可直接读取 Prettier 或 oxfmt 配置,无需安装 prettier 包。在 1.4.3 及更早版本中,它会报错 Script not found "fmt"。
bun fmt # format in place
bun fmt --check # write nothing; exit 1 if a file needs formatting, 2 on an error
bun fmt --staged # pre-commit: format staged files and stage them again
bun fmt --changed # files that differ from the default branch (--changed=<ref>)
bun fmt --init # add a [fmt] section to bunfig.toml
- **
fmt脚本优先,**与bun check中的check脚本行为相同:bun fmt --check会运行fmt脚本并附加--check,无论从 shell 还是从其他脚本调用都是如此。在脚本、钩子和 CI 中,请写bun fmt --no-script。 - 无论顺序如何,
--write都优先于--check——bun fmt --check --write会执行格式化并以 0 退出。 - 配置可以写在
bunfig.toml的[fmt]中(使用驼峰命名的 Prettier 选项;未知键会以退出码 2 退出),也可以使用现有的.prettierrc/.oxfmtrc.json。sortImports、sortTailwindcss、sortPackageJson和jsdoc是可选功能,用于替代对应的 Prettier 插件。 bun format不是别名:它会运行format脚本。
参考:关于退出码、配置优先级、插件、忽略规则、处理部分暂存文件时的
--staged,以及 CI,请参阅references/formatting.md。
测试
Bun 内置了一个兼容 Jest 类语法的测试运行器。
运行测试
bun test # Run all test files
bun test file.test.ts # Run specific file
bun test foo bar # Positional args filter by FILE path, not test name
bun test -t "pattern" # Filter by TEST NAME (regex); --grep is an alias
bun test --timeout 10000 # Set timeout (ms)
bun test --bail # Stop on first failure
bun test --bail 5 # Stop after 5 failures
bun test --rerun-each 3 # Run each test 3 times
bun test --retry 3 # Default retry count for flaky tests
bun test --only # Run only tests marked with .only
bun test --todo # Include .todo tests
bun test --only-failures # Print failures and the summary only
bun test --pass-with-no-tests # Exit 0 when nothing matches (monorepos)
bun test --check # Type check test files + imports first; no test runs on an error (v1.4.3+)
--filter 不是测试名称筛选器。 在 bun test 中,--filter 是另一个文件路径筛选器,和位置参数完全相同;-F 会被拒绝。(工作区选择是包管理器的功能:bun run --filter '*' test。)传入测试名称通常不会匹配任何文件,随后 bun test 会以 1 退出(“did not match any test files”)——因此这个错误会导致运行失败,而不是悄悄通过,但仍然不会运行任何测试。筛选测试名称请使用 -t / --test-name-pattern / --grep。--pass-with-no-tests 会将退出码 1 改为 0,这就会掩盖该错误。
覆盖率
bun test --coverage # Enable code coverage
bun test --coverage-reporter text # Coverage format: 'text' and/or 'lcov' -- there is no 'json'
bun test --coverage-dir ./cov # Output directory
自 v1.4.3 起,--coverage-reporter 会隐式启用 --coverage。此前,单独使用 --coverage-reporter=lcov 只会运行测试,不会生成报告。
1.4.4 中的变更——计数更严格。 从未运行的代码不再计为已覆盖:单独位于一行的 ||、&&、?? 或 ?: 未执行的分支,被 ?. 或 ??= 跳过的代码,以及函数未恢复执行时 await 之后的代码。升级后,即使代码未变,% Lines 也可能下降——请重新设定 coverageThreshold 基线。% Funcs 不再计入隐式构造函数、字段初始化器和 static 代码块,因此可能上升。某个文件在 1.4.3 上的行覆盖率为 100% / 函数覆盖率为 83%,在 1.4.4 上则为 67% / 100%。
并行执行、分片与隔离
bun test --parallel # Files across N worker processes (default: CPU count)
bun test --parallel=4 --isolate # Explicit worker count
bun test --isolate # Fresh globalThis per file, same process (Jest/Vitest default)
bun test --shard=1/3 # One CI runner's slice of the files
bun test --changed=main # Only files your diff reaches (walks the import graph)
bun test --timings=t.json --update-timings # Record per-file durations
bun test --parallel --shard=1/3 --timings=t.json # Balance by wall time, not file count
--parallel会隐式启用--isolate;使用--no-isolate可退出隔离模式,使每个工作进程复用同一个全局对象和模块注册表。--isolate会在文件之间重置globalThis和模块注册表,并关闭文件遗留的服务器、套接字、监视器和子进程,从而解决“单独运行时通过,在测试套件中失败”的问题。转译后的源代码和字节码会在不同全局对象之间保持缓存,因此开销很低。- 工作进程会将其从 1 开始计数的槽位公开为
JEST_WORKER_ID/BUN_TEST_WORKER_ID,因此依赖JEST_WORKER_ID设置数据库或端口的 Jest 配置可以原样使用。 - 覆盖率和 JUnit 输出会在各工作进程间合并;
--bail会停止所有工作进程。 --timings(v1.4+)会按耗时而非文件数量均衡分片,并按耗时从长到短写入文件,因此也可用作慢速测试报告。- 1.4.1 会阻止使用
mock()、spyOn()、mock.module()或Bun.plugin()的文件在--isolate下保留之前的模块图,使大规模测试套件的内存占用保持稳定。
测试文件匹配模式
默认情况下,Bun 会查找匹配以下模式的文件:*.test.{ts,tsx,js,jsx}、*_test.{ts,tsx,js,jsx}、*.spec.{ts,tsx,js,jsx}、*_spec.{ts,tsx,js,jsx},以及 __tests__/ 目录中的文件。使用 --path-ignore-patterns <glob> 或在 bunfig.toml 中配置 test.pathIgnorePatterns 可排除路径。
快照测试
bun test --update-snapshots # Update snapshot files
监视模式
bun test --watch # Re-run on file changes
参考:测试 API、模拟、生命周期钩子和覆盖率配置,请参阅
references/testing.md。
打包与编译
打包
bun build ./src/index.ts --outdir ./dist # Bundle to directory
bun build ./src/index.ts --outfile ./dist/out.js # Bundle to single file
bun build ./src/index.ts --target browser # Target: browser (default), bun, node
bun build ./src/index.ts --format esm # Format: esm (default), cjs, iife
bun build ./src/index.ts --minify # Minify output
bun build ./src/index.ts --sourcemap external # Sourcemaps: external, inline, linked, none
bun build ./src/index.ts --splitting # Code splitting (ESM only)
bun build ./src/index.ts --splitting --min-chunk-size=16384 # Fold tiny side-effect-free chunks into their loaders (v1.4.1+)
bun build ./src/index.ts --outdir ./dist --check # Type check first; nothing is written on an error (v1.4.3+)
1.4.1 中的更改——拆分输出。 入口与其延迟加载路由共享的代码会保留在入口的代码块中(文件更少、体积更小);浏览器构建会为入口或 import() 加载的每个代码块添加 <link rel="modulepreload">(使用 --no-module-preload 禁用);--target bun 会将对 ES 模块的 require() 转换为独立代码块(使用 --no-split-require 内联);export * as / const { x } = await import() 会对未使用的导出进行摇树优化——zod 和 effect 打包后的体积可缩小 50-80%。构建输出的快照测试将发生变化。
1.4.3 中的更改——代码块名称。 大型 --splitting 构建不再会因 Multiple files share the same output path 而失败:两个不同代码块的 8 位 [hash] 冲突时,都会增加额外字符,直到彼此不同。[hash9] 到 [hash13] 用于设置更宽的最小长度([hash13] 是完整的 64 位哈希;1.4.2 会将该标记按字面输出并导致失败)。共享代码不再合并到名称中没有 [hash] 的入口代码块中,因此使用查询字符串加载的入口(index.js?v=1)不会运行两次——这是 1.4.1 中引入的回归问题。metafile.inputs 中每个拆分的 import() 都会在 entryPoint 中列出其加载的文件。
独立可执行文件
bun build ./src/cli.ts --compile # Create self-contained executable
bun build ./src/cli.ts --compile --target bun-linux-x64 # Cross-compile
bun build ./src/cli.ts --compile --minify # Minified executable
可用的编译目标:bun-linux-x64、bun-linux-arm64、bun-darwin-x64、bun-darwin-arm64、bun-windows-x64。
浏览器目标(v1.3.10+)——编译为自包含的 HTML 文件:
bun build --compile --target=browser ./app.tsx --outfile ./dist/app.html
构建选项
bun build ... --external pkg # Exclude from bundle
bun build ... --define 'KEY=VALUE' # Define compile-time constants
bun build ... --loader .ext=type # Custom loaders (js, jsx, ts, tsx, json, css, text, file, base64, dataurl, binary)
bun build ... --entry-naming [dir]/[name].[ext] # Output naming pattern
bun build ... --chunk-naming 'chunk-[hash13].[ext]' # Wider minimum hash: [hash9]..[hash13] (v1.4.3+)
bun build ... --public-path /cdn/ # Public path prefix for assets
bun build ... --react-compiler # React auto-memoization, no Babel/SWC (v1.4+)
bun build ... --metafile meta.json # esbuild-format build metadata
bun build ... --metafile-md meta.md # Module graph as Markdown, for reading or an LLM (v1.3.8+)
bun build ... --feature=FLAG # Compile-time flag for `feature()` from bun:bundle
bun build ./src/cli.ts --compile --asset ./public --asset ./templates # Embed files/dirs (v1.4+)
bun build ./src/cli.ts --compile --bytecode --bytecode-depth=1 # Bytecode for top-level + one nesting level (v1.4.1+)
bun build ... --no-deprecated-namespace-object-setters # Getter-only `import * as ns` objects, the future default (v1.4.1+)
--asset(v1.4+)会将文件或目录嵌入 --compile 可执行文件,同时保留原始文件名,因此 path.join(import.meta.dir, ...) 的解析结果与磁盘上的路径一致。node:fs 会将 /$bunfs/ 视为真实目录树,因此 readdirSync(包括 recursive / withFileTypes)可在二进制文件内部正常工作——启动时会枚举目录的静态文件服务无需修改即可运行。
v1.3.4 中的更改: --compile 二进制文件不再从运行时工作目录自动加载 tsconfig.json 或 package.json(可通过 --compile-autoload-tsconfig / --compile-autoload-package-json 重新启用);.env 和 bunfig.toml 仍会自动加载。
v1.3.9 起,--bytecode 支持 ES 模块(--format=esm,需要 --compile),可使用顶层 await、
import.meta、动态导入和代码拆分——此前它会强制使用 CommonJS。
从 v1.4.1 起,字节码的体积约为源代码的 3 倍,而非 9 倍;--bytecode-depth=N
会将提前编译限制在 N 层嵌套(更深层的函数会在首次调用时编译);使用 --bytecode 进行交叉编译时,所有目标均可用,包括从 macOS 或 Linux 编译 bun-windows-x64,且输出逐字节相同。
配置文件引导的字节码布局(v1.4.3+)。 --bytecode-order 会将记录的运行中使用的字节码放到 --compile --bytecode 可执行文件的前部,减少读取和解码自身内容的量(某大型 CLI 的冷启动时间从 1.01 秒降至 0.53 秒)。该选项需要 --compile --bytecode。
bun build ./src/cli.ts --compile --bytecode --outfile mycli # 1. build
BUN_BYTECODE_ORDER_OUT=mycli.order ./mycli --help # 2. run it as users do; written on exit
bun build ./src/cli.ts --compile --bytecode --bytecode-order=mycli.order --outfile mycli # 3. rebuild with the profile
函数通过其语法哈希进行匹配,因此上周的配置文件仍然适用——请将其提交到代码库或缓存起来。--bytecode-order=a.order,b.order 可指定多个配置文件,并按常用程度排序;bun:jsc 中的 bytecodeOrderStats() 会报告配置文件覆盖了多少运行内容。--compile-jit-policy <n> 会以按 n 缩放的 JIT 提升阈值启动可执行文件,使只运行一次的启动代码留在解释器中;应用进入交互状态后,调用一次 Bun.unsafe.setJITPolicy(1)。--no-optimize-bytecode 会跳过构建时的字节码优化器。
参考:完整选项请参阅
references/bundling-and-compilation.md。
项目初始化
bun init # Initialize new project (creates package.json, tsconfig.json, index.ts)
bun init -y # Accept defaults, no template picker
bun init --react # React template (also --react=tailwind, --react=shadcn)
bun init --minimal # Type definitions only
bun create template-name # Create from template
bun create next-app my-app # Example: create Next.js app
bun init 还会将 Bun 自带的 Agent 规则 CLAUDE.md 写入项目根目录(从 node_modules/bun-types/CLAUDE.md 复制而来)——其中包括“使用 bun,而不是 node/npm”、API 替换列表,以及 HTML 导入的前端模式。建议在新的 Bun 项目中运行它:这样可以为在仓库中工作的每个 Agent 提供相同的基准,并指向随附的文档。
1.4.3 中的变更: bun init 会添加 "typecheck": "bun check" 脚本(如果项目中已有 check 脚本,则将其改为 bun --check),并且复制的规则中使用 bun check,而不是 tsc --noEmit。它仍会添加 "@types/bun": "latest" 和 "types": ["bun"],但每次 Bun 发布后的至少一天内,这都会解析到上一个版本——请将其替换为 bun-types(见“检查版本”)。
1.4 中的变更: bun init 会写入 typescript: ^7(之前写入的是 ^5,或在 React 模板中不写入),并且当 stdin 为非 TTY(CI、管道传入的 spawn)时,它会改为执行 bun init -y,而不是打开模板选择器。现在,当 stdin 为非 TTY 时,bun update -i 会以状态码 1 退出——请改用 bun update 或 bun outdated。
配置(bunfig.toml)
主要章节:
[run]
bun = true # Always use Bun runtime (not Node)
[install]
exact = true # Pin exact versions by default
peer = false # Don't auto-install peer deps
production = false # Include devDeps
frozenLockfile = false # Don't fail on lockfile mismatch
globalDir = "~/.bun/install/global" # Global install location
linker = "isolated" # "isolated" or "hoisted" -- see gotchas
globalStore = true # Share package files across projects (requires isolated)
offline = false # true: never touch the network, every package must be cached (v1.4.1+)
prefer = "online" # "offline": cached metadata regardless of age (v1.4.1+); "latest": always check
minimumReleaseAge = "3d" # Supply-chain delay; units are v1.4.4+ ("90m", "12 hours"), a number is seconds
minimumReleaseAgeExcludes = ["@types/bun", "[email protected]"] # name: every version; name@version: that release (v1.4.4+)
[install.scopes]
"@myorg" = { token = "$NPM_TOKEN", url = "https://npm.pkg.github.com/" }
[fmt] # bun fmt (v1.4.4+): every Prettier option by its camelCase name
printWidth = 100
sortImports = true
[test]
coverage = false # Enable coverage by default
coverageReporter = ["text", "lcov"]
timeout = 5000 # Default test timeout
pathIgnorePatterns = ["**/e2e/**"] # Exclude test files by glob
[bundle]
entryPoints = ["./src/index.ts"]
outdir = "./dist"
参考: 完整的 bunfig.toml 参考请见
references/configuration.md。
调试与分析
bun --inspect file.ts # Start debugger (WebSocket, connect via Chrome DevTools)
bun --inspect-wait file.ts # Wait for debugger to attach before executing
bun --inspect-brk file.ts # Break on first line
bun --cpu-prof file.ts # Generate CPU profile
bun --cpu-prof-md file.ts # CPU profile as Markdown (v1.3.7+)
bun --heap-prof file.ts # Generate heap profile
bun --heap-prof-md file.ts # Heap profile as Markdown (v1.3.7+)
BUN_JSC_logJITCodeForPerf=1 bun file.ts # Linux perf integration
环境变量
bun --env-file .env file.ts # Load .env file
bun --env-file .env.local --env-file .env file.ts # Load multiple (left takes precedence)
Bun 默认会根据 NODE_ENV 自动加载 .env、.env.production、.env.local、.env.production.local。
可替代外部工具的内置功能
Bun 内置了许多功能,无需外部程序包或工具:
原生 TypeScript
Bun 可直接运行 .ts、.tsx 文件——无需 tsc、ts-node 或 tsx。转译器已内置于运行时中。使用 bun file.ts 即可立即运行任何 TypeScript 文件。
内置类型检查器
bun check(v1.4.3+)可替代 tsc --noEmit,而 --check 会在类型检查通过后才运行 bun <file>、bun test 和 bun build——无需 typescript 程序包。只有在需要生成 .d.ts 文件时才保留 tsc。
内置格式化工具
bun fmt(v1.4.4+)可替代 prettier、oxfmt 和 lint-staged 来进行格式化,也可替代 Prettier 的导入排序、Tailwind、package.json 和 Svelte 插件。它会读取现有的 Prettier 或 oxfmt 配置。
工作区目录
Bun 支持在 package.json 中使用 catalog: 协议,在 monorepo 工作区中集中管理依赖版本——无需使用 syncpack 或 manypkg 等工具:
// Root package.json
{
"workspaces": ["packages/*"],
"catalog": {
"react": "^19.0.0",
"typescript": "^5.7.0"
}
}
// packages/app/package.json
{
"dependencies": {
"react": "catalog:"
}
}
内置测试运行器
bun test 是完整兼容 Jest 的测试运行器,支持快照测试、模拟和覆盖率——无需 jest、vitest 或 mocha。
内置打包器
bun build 在许多场景中可替代 esbuild、webpack、rollup。支持代码拆分、摇树优化、压缩和独立可执行文件编译。
内置 SQLite
import { Database } from 'bun:sqlite'——零依赖的 SQLite3,支持预处理语句和事务。无需 better-sqlite3 或 sql.js。
内置 Shell
Bun.$ 标签模板——跨平台 Shell 执行,并自动转义。可替代 execa、shelljs、zx。
内置文件 I/O
Bun.file() 和 Bun.write()——无需导入 fs 即可快速执行文件操作。可自动检测 MIME 类型。
内置 Glob
new Bun.Glob(pattern)——快速进行 Glob 匹配和文件扫描。可替代 glob、fast-glob、minimatch。
内置密码哈希
Bun.password.hash() 和 .verify(),支持 bcrypt 和 argon2id。可替代 bcrypt、argon2 程序包。
内置压缩
Bun.gzipSync()、Bun.deflateSync()、Bun.zstdCompressSync()——无需 zlib 包装程序包。
内置 Semver
Bun.semver.satisfies()、.order()——可替代 semver 程序包。
内置运行时 API
有关 Bun 的内置运行时辅助功能(Bun.s3、Bun.redis、Bun.Archive、JSONC、JSON5、JSONL、markdown、cron),请参阅 bun-api 技能。
零配置前端开发服务器
bun ./index.html — 提供 HTML 服务,并自动打包 JS/TS/CSS,支持 HMR 和 React Fast Refresh。对于简单项目,可替代 Vite/Webpack 开发服务器。
ES 装饰器
原生支持 TC39 标准 ES 装饰器(v1.3.10+)——无需在 tsconfig 中设置 experimentalDecorators。
关键注意事项
- 在 Bun 项目中始终使用
bun,不要使用npm/node/npx - 锁文件格式:新项目默认使用
bun.lock(文本格式,v1.2+)。旧版bun.lockb是二进制文件。不要与package-lock.json混用。v1.4+ 会写入lockfileVersion: 2(使用嵌套或按版本指定的覆盖项时则为3)。Bun 1.3 无法读取版本 3——如果仓库的 CI 固定使用较旧版本的 Bun,提交前请检查 - trustedDependencies:生命周期脚本(postinstall 等)只会为
package.json中列在trustedDependencies下的包运行。v1.3.5+ 默认信任列表只适用于来自 npm 注册表的包,因此名为esbuild的file:/link:/git:/github:依赖不会因真正的 esbuild 条目而获得信任——请自行将其列入。v1.4+ 会按完整包名匹配条目,而不是按截断的哈希匹配 --bun标志:某些工具(例如 Next.js)即使通过bun run启动,默认也会使用 Node.js。使用--bun或在bunfig.toml中设置[run] bun = true,以强制使用 Bun 运行时- 工作区协议:在
package.json中使用"workspace:*"引用工作区包 - 全局二进制文件:使用
bun add -g安装,位于~/.bun/bin/ - Node.js 兼容性:Bun 实现了大多数 Node.js API,但部分边界情况有所不同。请查看 https://bun.sh/docs/runtime/nodejs-apis 了解兼容性
- TypeScript:Bun 无需编译步骤即可原生运行 TypeScript。它使用自己的转译器(而非 tsc),运行时不会进行类型检查——请使用
bun check或--check(v1.4.3+) - 自动安装:Bun 可以在导入时自动安装缺失的包(默认禁用,可在
bunfig.toml中通过[install] auto = true启用) bun run与bun:bun run script会运行package.json脚本;bun file.ts会直接运行文件。bun script会先尝试运行脚本,再回退到运行文件--filter不是测试名称筛选器。 在bun test中,它筛选的是文件路径,与位置参数相同(不接受-F;工作区选择方式为bun run --filter '*' test)。bun test -t <regex>(或--grep)才会筛选测试名称。用错会导致找不到任何匹配项并以状态码 1 退出——除非设置了--pass-with-no-tests,此时它会成功退出,但实际上什么也没测- 覆盖率报告器仅支持
text和lcov——--coverage-reporter=json会被拒绝。从 v1.4.3 起,该标志会隐含启用--coverage - 从 v1.4 起,
bunfig.toml使用严格 TOML 语法。 未加引号的值、键值对之间缺少换行,以及超出Number.MAX_SAFE_INTEGER范围的整数,都会导致启动时出现SyntaxError。linker = isolated必须写为linker = "isolated" - 以
node名称调用 Bun 时不再加载.env(v1.4+)。 在bun --bun、bunx --bun或node符号链接下,调用node的脚本会发现这些变量的值为undefined。请传入--env-file,与 Node 的行为一致 - 现有项目默认不会启用 isolated linker——是否选择它取决于锁文件的
configVersion,而非 Bun 版本。请参阅上文的“安装布局” - x64 构建仅提供 baseline 版本(v1.4+)。
-march=haswell构建已移除;-baseline下载 URL 和 npm 包仍然存在,且包含相同的二进制文件;CPU lacks AVX support警告已移除 bun feedback已在 1.4 中移除- 打包后的命名空间对象将变为仅支持 getter。 目前,
bun build中的import * as ns/export * as ns会静默接受ns.x = 1;现在可通过--no-deprecated-namespace-object-setters(或deprecatedNamespaceObjectSetters: false)提前启用未来默认行为(v1.4.1+) - 在 1.4.1 之前,
bun run --filter、--workspaces、--parallel和--sequential会忽略自动发现的bunfig.toml,除非传入了--config;此外,当[define]或--drop发生变化后,bun run也会对大小不小于 4 KiB 的文件重复使用过时的转译缓存 - Bun 1.4.1 的
bun build可能会把嵌套的var重命名为同一代码块中的let,导致导入 Elysia 的打包文件因SyntaxError: Cannot declare a var variable that shadows a let/const/class variable而无法加载;而且let也可能使用参数或catch绑定的名称,进而计算出错误值。该问题已在 1.4.2 中修复——请升级,而不要修补输出结果;打包时不要固定使用 1.4.1 check脚本会遮蔽bun check(v1.4.3+)。 当package.json定义了check时,bun check会运行该脚本——其他脚本中调用时也一样,但check脚本自身启动的脚本除外——因此bun init生成的"typecheck": "bun check"会转而运行 lint 脚本。bun --check无论如何都会进行类型检查;v1.4.4+ 的bun check --no-script也会进行类型检查:请在脚本中使用其中一种。在旧版 Bun 上,"check": "bun check"会无限递归调用自身@types/bun的更新总是落后于 Bun 的每次发布,通常会晚一天或更久,因此bun check会拒绝最新的 API(TS2339、TS2353)。请改为依赖bun-types@<runtime-version>,并设置"types": ["bun-types"];在@types/bun旁安装bun-types不会改变类型检查使用的定义- 安装过程不再缓存被跳过的内容(v1.4.3+)。 在没有锁文件时,使用
--production或--omit安装不会下载被排除组中的 tarball,因此无法为之后完整的--offline安装预热缓存。请通过一次安装来预热缓存,确保安装相同的包且平台相同 - 从 1.4.3 起,
--disallow-code-generation-from-strings会强制生效——此前 Bun 会接受并忽略此选项。eval()和new Function()现在会在整个进程范围内抛出EvalError,包括 Workers;=strict还会阻止node:vm、data:/blob:导入以及返回源代码文本的插件,并拒绝--inspect。v1.4.4 中,=strict只运行随程序交付的代码:--compile可执行文件会拒绝磁盘上的 JavaScript 文件(包括它刚写入的文件),而返回任何加载器的contents的插件也会被拒绝;但包含 JSON 的data:URL 可以使用(1.4.3 会拒绝) fmt脚本会遮蔽bun fmt(v1.4.4+),并接收其标志,即使是在其他脚本中调用bun fmt也一样。请在脚本、钩子和 CI 中使用bun fmt --no-script。无论顺序如何,-w/--write都会覆盖--check- 包管理器命令会拒绝未知标志(v1.4.4+),并转换 npm/Yarn/pnpm 的标志。CI 命令中某个 Bun 1.4.3 会静默忽略的标志,现在可能导致以状态码 1 退出;而
bun add --save-dev在 1.4.3 中会保存到dependencies,现在则会保存到devDependencies bun lint仅适用于 canary 版本。bun-types1.4.4 在docs/lint/下记录了此命令,但稳定版 1.4.4 会运行项目的lint脚本- 1.4.4 中的覆盖率数值会发生变化:即使代码没有更改,
% Lines也可能低于coverageThreshold,因为被跳过的分支和从未恢复执行的await之后的行不再计为已覆盖 - 在 1.4.4 之前,
bun install --dry-run会运行项目的生命周期脚本;而在 1.4.3 中,bun check --no-script会运行check脚本并附加--no-script——在旧版 Bun 上,这两者都不能作为只读探测安全使用
参考资料
references/migration-1.4.md-- CLI、包管理器、打包器和测试运行器从 1.3 到 1.4.4 的变更references/package-management.md-- 安装、添加、更新、审计、pm 标志、工作区、链接器、CI 缓存references/running-and-execution.md-- 运行时标志、bunx、性能分析、监视/热更新、代码生成锁定references/type-checking.md--bun check、--check、输出格式、TypeScript 7 默认设置、单体仓库、CIreferences/formatting.md--bun fmt、退出代码、[fmt]配置、Prettier/oxfmt 配置、git 钩子、CIreferences/testing.md-- 测试运行器 API、模拟、覆盖率、CI 配置references/bundling-and-compilation.md--bun build、目标、独立可执行文件references/configuration.md-- 完整的bunfig.toml参考references/allowlist.md-- 可复制粘贴的Bash(command:*)权限模式