mcpField
B
bun-cli

bun-cli

github.com/dmythro开发7216 次安装4 天前更新
代码仓库

关于 bun-cli

bun-cli 是面向 Bun 项目开发者的命令行技能,汇总运行时、包管理、构建、测试、类型检查和格式化用法。它强调依据已安装版本核对功能与文档,并在 Bun 项目中统一使用 Bun 命令。

主要功能

  1. 01运行 JavaScript 和 TypeScript
  2. 02管理依赖与工作区
  3. 03打包、测试与类型检查
  4. 04格式化代码
  5. 05按版本核对命令和行为

适用场景

  1. 01在 Bun 项目中运行脚本和测试
  2. 02安装、更新或审计依赖
  3. 03排查版本升级带来的行为变化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dmythro/agent-skills --skill bun-cli

安装后在 Claude Code 中输入/bun-cli确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
allowlist.md
bundling-and-compilation.md
configuration.md
formatting.md
migration-1.4.md
package-management.md
running-and-execution.md
testing.md
type-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、--assetbun.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
  1. 依赖 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/nodeBun 对应命令
npm installbun install
npm install pkgbun add pkg
npm install -D pkgbun add -d pkg
npm install -g pkgbun add -g pkg
npm uninstall pkgbun remove pkg
npm updatebun update
npm run scriptbun run script
npx commandbunx command
node file.jsbun file.js
node --watch file.jsbun --watch file.js
npm testbun test
tsc --noEmitbun 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 packbun pm pack
npm publishbun publish
npm info pkgbun info pkg
npm outdatedbun outdated
npm auditbun audit
npm linkbun 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 的布局。它们的重要性超乎表面看起来。

链接器
hoistedisolated
布局npm 风格的扁平 node_modules链接到 node_modules/.bun/ 的符号链接(pnpm 风格)
幽灵依赖静默解析解析失败,这是应有的行为
默认情况configVersion = 0(任何项目),或不使用工作区的 configVersion = 1configVersion = 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

启用前值得了解的影响:

  1. 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 风格布局的注意事项相同。
  2. 每个项目共享相同的 inode。 编辑 node_modules/ 下的文件会影响此计算机上的所有项目。请使用 bun patch。
  3. 真正的幽灵依赖将无法解析。 软件包的真实路径会指向缓存,因此隐藏的 node_modules/.bun/node_modules/ 层不再处于软件包内部的解析路径上。可通过声明依赖修复,或设置 globalStore = false。
  4. 某些条目仍保留在项目本地:已修补的软件包、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。

关键注意事项

  1. 在 Bun 项目中始终使用 bun,不要使用 npm/node/npx
  2. 锁文件格式:新项目默认使用 bun.lock(文本格式,v1.2+)。旧版 bun.lockb 是二进制文件。不要与 package-lock.json 混用。v1.4+ 会写入 lockfileVersion: 2(使用嵌套或按版本指定的覆盖项时则为 3)。Bun 1.3 无法读取版本 3——如果仓库的 CI 固定使用较旧版本的 Bun,提交前请检查
  3. trustedDependencies:生命周期脚本(postinstall 等)只会为 package.json 中列在 trustedDependencies 下的包运行。v1.3.5+ 默认信任列表只适用于来自 npm 注册表的包,因此名为 esbuild 的 file:/link:/git:/github: 依赖不会因真正的 esbuild 条目而获得信任——请自行将其列入。v1.4+ 会按完整包名匹配条目,而不是按截断的哈希匹配
  4. --bun 标志:某些工具(例如 Next.js)即使通过 bun run 启动,默认也会使用 Node.js。使用 --bun 或在 bunfig.toml 中设置 [run] bun = true,以强制使用 Bun 运行时
  5. 工作区协议:在 package.json 中使用 "workspace:*" 引用工作区包
  6. 全局二进制文件:使用 bun add -g 安装,位于 ~/.bun/bin/
  7. Node.js 兼容性:Bun 实现了大多数 Node.js API,但部分边界情况有所不同。请查看 https://bun.sh/docs/runtime/nodejs-apis 了解兼容性
  8. TypeScript:Bun 无需编译步骤即可原生运行 TypeScript。它使用自己的转译器(而非 tsc),运行时不会进行类型检查——请使用 bun check 或 --check(v1.4.3+)
  9. 自动安装:Bun 可以在导入时自动安装缺失的包(默认禁用,可在 bunfig.toml 中通过 [install] auto = true 启用)
  10. bun run 与 bun:bun run script 会运行 package.json 脚本;bun file.ts 会直接运行文件。bun script 会先尝试运行脚本,再回退到运行文件
  11. --filter 不是测试名称筛选器。 在 bun test 中,它筛选的是文件路径,与位置参数相同(不接受 -F;工作区选择方式为 bun run --filter '*' test)。bun test -t <regex>(或 --grep)才会筛选测试名称。用错会导致找不到任何匹配项并以状态码 1 退出——除非设置了 --pass-with-no-tests,此时它会成功退出,但实际上什么也没测
  12. 覆盖率报告器仅支持 text 和 lcov——--coverage-reporter=json 会被拒绝。从 v1.4.3 起,该标志会隐含启用 --coverage
  13. 从 v1.4 起,bunfig.toml 使用严格 TOML 语法。 未加引号的值、键值对之间缺少换行,以及超出 Number.MAX_SAFE_INTEGER 范围的整数,都会导致启动时出现 SyntaxError。linker = isolated 必须写为 linker = "isolated"
  14. 以 node 名称调用 Bun 时不再加载 .env(v1.4+)。 在 bun --bun、bunx --bun 或 node 符号链接下,调用 node 的脚本会发现这些变量的值为 undefined。请传入 --env-file,与 Node 的行为一致
  15. 现有项目默认不会启用 isolated linker——是否选择它取决于锁文件的 configVersion,而非 Bun 版本。请参阅上文的“安装布局”
  16. x64 构建仅提供 baseline 版本(v1.4+)。 -march=haswell 构建已移除;-baseline 下载 URL 和 npm 包仍然存在,且包含相同的二进制文件;CPU lacks AVX support 警告已移除
  17. bun feedback 已在 1.4 中移除
  18. 打包后的命名空间对象将变为仅支持 getter。 目前,bun build 中的 import * as ns / export * as ns 会静默接受 ns.x = 1;现在可通过 --no-deprecated-namespace-object-setters(或 deprecatedNamespaceObjectSetters: false)提前启用未来默认行为(v1.4.1+)
  19. 在 1.4.1 之前,bun run --filter、--workspaces、--parallel 和 --sequential 会忽略自动发现的 bunfig.toml,除非传入了 --config;此外,当 [define] 或 --drop 发生变化后,bun run 也会对大小不小于 4 KiB 的文件重复使用过时的转译缓存
  20. 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
  21. 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" 会无限递归调用自身
  22. @types/bun 的更新总是落后于 Bun 的每次发布,通常会晚一天或更久,因此 bun check 会拒绝最新的 API(TS2339、TS2353)。请改为依赖 bun-types@<runtime-version>,并设置 "types": ["bun-types"];在 @types/bun 旁安装 bun-types 不会改变类型检查使用的定义
  23. 安装过程不再缓存被跳过的内容(v1.4.3+)。 在没有锁文件时,使用 --production 或 --omit 安装不会下载被排除组中的 tarball,因此无法为之后完整的 --offline 安装预热缓存。请通过一次安装来预热缓存,确保安装相同的包且平台相同
  24. 从 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 会拒绝)
  25. fmt 脚本会遮蔽 bun fmt(v1.4.4+),并接收其标志,即使是在其他脚本中调用 bun fmt 也一样。请在脚本、钩子和 CI 中使用 bun fmt --no-script。无论顺序如何,-w/--write 都会覆盖 --check
  26. 包管理器命令会拒绝未知标志(v1.4.4+),并转换 npm/Yarn/pnpm 的标志。CI 命令中某个 Bun 1.4.3 会静默忽略的标志,现在可能导致以状态码 1 退出;而 bun add --save-dev 在 1.4.3 中会保存到 dependencies,现在则会保存到 devDependencies
  27. bun lint 仅适用于 canary 版本。 bun-types 1.4.4 在 docs/lint/ 下记录了此命令,但稳定版 1.4.4 会运行项目的 lint 脚本
  28. 1.4.4 中的覆盖率数值会发生变化:即使代码没有更改,% Lines 也可能低于 coverageThreshold,因为被跳过的分支和从未恢复执行的 await 之后的行不再计为已覆盖
  29. 在 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 默认设置、单体仓库、CI
  • references/formatting.md -- bun fmt、退出代码、[fmt] 配置、Prettier/oxfmt 配置、git 钩子、CI
  • references/testing.md -- 测试运行器 API、模拟、覆盖率、CI 配置
  • references/bundling-and-compilation.md -- bun build、目标、独立可执行文件
  • references/configuration.md -- 完整的 bunfig.toml 参考
  • references/allowlist.md -- 可复制粘贴的 Bash(command:*) 权限模式

评论

支持 Markdown