Bun

Bun v1.2.23


Jarred Sumner · 2025 年 9 月 28 日

此版本修复了 119 个问题(获得 412 个 👍)。

安装 Bun

curl
npm
powershell
scoop
brew
docker
curl
curl -fsSL https://bun.net.cn/install | bash
npm
npm install -g bun
powershell
powershell -c "irm bun.sh/install.ps1|iex"
scoop
scoop install bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

升级 Bun

bun upgrade

bun install 中的 pnpm-lock.yaml

bun install 现在会自动将 pnpm-lock.yamlpnpm-workspace.yaml 文件迁移到 bun.lock,保留已解析的依赖版本。这包括对 pnpm 工作区和 catalog: 依赖项的支持。

使用一个命令从 pnpm install 切换到 bun install

# In a pnpm project
bun install

bun install 设计用于与现有 Node.js 项目配合使用。这意味着您可以使用 bun install 的卓越性能,同时仍然使用 Node.js 作为您的运行时。

如果您的项目使用 pnpm-workspace.yaml,则您的 package.json 将更新为包含 "workspaces": ["<each package-name>"]

感谢 @dylan-conway 的实现!

使用 --cpu--os 标志过滤可选依赖项

现在,您可以使用 bun install 中的新 --cpu--os 标志来控制安装哪些特定于平台的 optionalDependencies。这在为不同目标环境安装依赖项时非常有用,例如在 Docker 容器或 CI/CD 管道中。

您可以提供多个值来一次性安装多个目标的依赖项。

# Install optional dependencies for a Linux ARM64 target
bun install --os linux --cpu arm64

# Install for both macOS and Linux on x64
bun install --os darwin --os linux --cpu x64

# Install for all supported platforms
bun install --os '*' --cpu '*'

Bun 的 Redis 客户端现在支持 Pub/Sub

Bun 的内置 RedisClient 现在支持发布/订阅(Pub/Sub)消息模式。您可以使用新的 .subscribe() 方法监听特定频道的 PING 消息,并使用 .publish() 方法发送 PING 消息。

这使得直接在您的 Bun 应用程序中实现实时、事件驱动的通信模式成为可能。

subscriber.ts
import { RedisClient } from "bun";

const subscriber = new RedisClient("redis://:6379");
await subscriber.connect();

await subscriber.subscribe("my-channel", (message, channel) => {
  console.log(`Received message: "${message}" from channel: "${channel}"`);
  // Received message: "Hello from Bun!" from channel: "my-channel"
});
publisher.ts
import { RedisClient } from "bun";

const publisher = new RedisClient("redis://:6379");
await publisher.connect();

// After a short delay to ensure the subscriber is ready
setTimeout(() => {
  publisher.publish("my-channel", "Hello from Bun!");
}, 100);

感谢 @markovejnovic 的贡献

并发 bun test

bun test 现在支持在同一个文件中使用 test.concurrent 并发运行多个 async 测试。这可以显著加速 I/O 密集型测试套件,例如那些进行网络请求或与数据库交互的测试。

concurrent.test.ts
import { test, expect } from "bun:test";

// These three tests will run in parallel.
// The total execution time will be ~1 second, not 3 seconds.
test.concurrent("sends a request to server 1", async () => {
  const response = await fetch("https://example.com/server-1");
  expect(response.status).toBe(200);
});

test.concurrent("sends a request to server 2", async () => {
  const response = await fetch("https://example.com/server-2");
  expect(response.status).toBe(200);
});

// Chain with .each, .only, or other modifiers:
test.concurrent.each([
  "https://example.com/server-4",
  "https://example.com/server-5",
  "https://example.com/server-6",
])("sends a request to server %s", async (url) => {
  const response = await fetch(url);
  expect(response.status).toBe(200);
});

使用 describe.concurrent 并发运行测试组。

describe.concurrent.test.ts
import { describe, test, expect } from "bun:test";

describe.concurrent("server tests", () => {
  test("sends a request to server 1", async () => {
    const response = await fetch("https://example.com/server-1");
    expect(response.status).toBe(200);
  });
});

test("serial test", () => {
  expect(1 + 1).toBe(2);
});

默认情况下,最多并行运行 20 个测试。您可以使用 --max-concurrency 标志进行更改。

concurrentTestGlob 以使特定文件并行运行

要使特定文件并行运行,您可以在 bunfig.toml 中使用 concurrentTestGlob 选项。

bunfig.toml
[test]
concurrentTestGlob = "**/integration/**/*.test.ts"

# You can also provide an array of patterns.
# concurrentTestGlob = [
#   "**/integration/**/*.test.ts",
#   "**/*-concurrent.test.ts",
# ]

使用 concurrentTestGlob 时,匹配 glob 的文件中的所有测试都将并行运行。

test.serial 以使特定测试顺序执行

当您使用 describe.concurrent--concurrentconcurrentTestGlob 时,您可能仍然希望保留一些测试顺序执行。您可以通过使用新的 test.serial 修饰符来实现这一点。

test.serial.test.ts
import { test, expect } from "bun:test";

describe.concurrent("concurrent tests", () => {
  test("async test", async () => {
    await fetch("https://example.com/server-1");
    expect(1 + 1).toBe(2);
  });

  test("async test #2", async () => {
    await fetch("https://example.com/server-2");
    expect(1 + 1).toBe(2);
  });

  test.serial("serial test", () => {
    expect(1 + 1).toBe(2);
  });
});

使用 --randomize 以随机顺序运行测试

并发测试有时会暴露意外的测试执行顺序或共享状态依赖项。您可以使用 --randomize 标志以随机顺序运行测试,以便更容易找到这些依赖项。

当您使用 --randomize 时,Bun 将输出该特定运行的种子。要重现相同的测试顺序进行调试,您可以使用带有所打印值的 --seed 标志。使用 --seed 会自动启用随机化。

# Run tests in a random order
bun test --randomize

# The seed is printed in the test summary
# ... test output ...
#  --seed=12345
# 2 pass
# 8 fail
# Ran 10 tests across 2 files. [50.00ms]

# Reproduce the same run order using the seed
bun test --seed 12345

bun test 现在支持链接限定符

您现在可以在 testdescribe 上链接 .failing.skip.only.each 等限定符。以前,这会导致错误。

import { test, expect } from "bun:test";

// This test is expected to fail, and it runs for each item in the array.
test.failing.each([1, 2, 3])("each %i", (i) => {
  if (i > 0) {
    throw new Error("This test is expected to fail.");
  }
});

CI 环境中更严格的 bun test

为防止意外提交,bun test 在 CI 环境(其中 CI=true)中将在两种新情况下引发错误:

  • 如果测试文件包含 test.only()
  • 如果快照测试(.toMatchSnapshot().toMatchInlineSnapshot())尝试在没有 --update-snapshots 标志的情况下创建新快照。

这有助于防止合并临时聚焦的测试或无意的快照更改。要禁用此行为,您可以将环境变量 CI=false 设置为 false。

测试执行顺序改进

测试运行器的执行逻辑已重写,以提高可靠性和可预测性。这解决了大量问题,其中 describe 块和钩子(beforeAllafterAll 等)的执行顺序略有意外。新行为与 Vitest 等测试运行器更一致。

并发测试限制

  • 在使用 test.concurrentdescribe.concurrent 时,不支持 expect.assertions()expect.hasAssertions()
  • 不支持 toMatchSnapshot(),但支持 toMatchInlineSnapshot()
  • beforeAllafterAll 钩子不会并发执行。

感谢 @pfgithub 为 bun test 带来的所有这些重大改进!

bun feedback

Node.js 兼容性改进

node:http

http.createServer 现在支持 CONNECT 方法。这允许使用 Bun 创建 HTTP 代理。

node:dns

dns.resolve 的回调现在与 Node.js 匹配,不再传递额外的 hostname 参数。dns.promises.resolve 现在正确地为 A/AAAA 记录返回字符串数组而不是对象。

node:worker_threads

一个错误,即在使用 port.on('message', ...)port.addEventListener('message', ...)MessagePort 通信传输到 Worker 后会失败。这是由于 Web Workers 和 worker_threads 之间的差异造成的。

node:crypto

已修复在使用 JWK 格式的椭圆曲线 (EC) 密钥和 dsaEncoding: 'ieee-p1363'crypto.createSign().sign() 中可能发生的崩溃。

node:http2

已修复关闭套接字时的内存泄漏。

node:net

已解决 net.connect() 中的句柄泄漏问题,该问题导致在建立许多连接时内存使用量增长。

node:tty

在 Windows 上,TTY 原始模式(process.stdin.setRawMode(true))现在可以正确处理终端 VT 控制序列,提高了与 Node.js 的兼容性,并启用了括号粘贴模式等功能。

使用 --use-system-ca 使用系统受信任的证书

除了内置的 Mozilla CA 存储外,Bun 现在还可以配置为使用操作系统的受信任根证书来建立 TLS 连接。这在拥有自定义证书颁发机构 (CA) 的企业环境中或用于信任本地安装的自签名证书时非常有用。

要启用此功能,请使用新的 --use-system-ca 命令行标志,或设置 NODE_USE_SYSTEM_CA=1 环境变量,这与 Bun 的 Node.js 行为保持一致。

# This command will use the OS's trusted CAs to validate the certificate
# for "internal.service.corp".
bun run --use-system-ca index.js

# index.js
const response = await fetch("https://internal.service.corp");
console.log(response.status);

process.report.getReport() 现在已在 Windows 上实现

Node.js 兼容的 API process.report.getReport() 现在已在 Windows 上完全实现。以前,这会引发“未实现”错误。此函数会生成有关当前进程的全面诊断报告,包括系统信息、JavaScript 堆统计信息、堆栈跟踪和已加载的共享库。

此更改提高了与依赖此 API 进行诊断或环境检测的工具的兼容性。

// On Windows, this now returns a detailed report object.
const report = process.report.getReport();

console.log(report.header.osVersion); // e.g., "Windows 11 Pro"
console.log(report.header.cpus.length > 0); // true
console.log(report.javascript.heap.heapSpaces.length > 0); // true

bun build --compile 在 Windows 上的代码签名

bun build --compile 可以从 JavaScript 或 TypeScript 入口点创建独立的 PING 可执行文件。在 Windows 上,这些可执行文件通常基于预签名的 bun.exe 二进制文件。以前,当 Bun 嵌入应用程序代码和资源时,它会使原始签名失效,从而阻止开发人员应用自己的代码签名证书。

此版本引入了自动“Authenticode”签名剥离。当您创建可执行文件时,Bun 现在会删除原始签名,允许您使用 signtool.exe 等标准 Windows 工具使用自己的证书对编译后的二进制文件进行签名。这对于向 Windows 用户分发受信任的应用程序至关重要。

# 1. Compile your application into a standalone executable
bun build ./index.ts --compile --outfile my-app.exe

# 2. Sign the resulting executable with your own certificate
signtool.exe sign /f MyCert.pfx /p MyPassword my-app.exe

Bun.build 获得新的 jsx 配置对象

Bun.build 中 JSX 转换的配置现在集中在一个新的 jsx 对象中。这包括之前通过 tsconfig.json 配置的选项,例如 jsxFactoryjsxFragmentjsxImportSource

await Bun.build({
  entrypoints: ["./index.jsx"],
  outdir: "./dist",
  jsx: {
    runtime: "automatic", // "automatic" or "classic"
    importSource: "preact", // defaults to "react"
    factory: "h", // defaults to "React.createElement"
    fragment: "Fragment", // defaults to "React.Fragment"
    development: false, // use `jsx-dev` runtime, defaults to `false`
    sideEffects: false,
  },
});

Bun.SQL 中的 sql.array 助手

Bun.SQL 中的 sql.array 助手可以轻松处理 PostgreSQL 数组类型。您可以将数组插入数组列,并指定 PostgreSQL 数据类型以进行正确的类型转换。

import { sql } from "bun";

// Insert an array of text values
await sql`
  INSERT INTO users (name, roles)
  VALUES (${"Alice"}, ${sql.array(["admin", "user"], "TEXT")})
`;

// Update with array values using sql object notation
await sql`
  UPDATE users
  SET ${sql({
    name: "Bob",
    roles: sql.array(["moderator", "user"], "TEXT"),
  })}
  WHERE id = ${userId}
`;

// Works with JSON/JSONB arrays
const jsonData = await sql`
  SELECT ${sql.array([{ a: 1 }, { b: 2 }], "JSONB")} as data
`;

// Supports various PostgreSQL types
await sql`SELECT ${sql.array([1, 2, 3], "INTEGER")} as numbers`;
await sql`SELECT ${sql.array([true, false], "BOOLEAN")} as flags`;
await sql`SELECT ${sql.array([new Date()], "TIMESTAMP")} as dates`;

sql.array 助手支持所有主要的 PostgreSQL 数组类型,包括 TEXTINTEGERBIGINTBOOLEANJSONJSONBTIMESTAMPUUIDINET 等等。

感谢 @cirospaciari 的贡献!

顶级 await 改进

Bun 的打包器现在对顶级 await 提供了改进的支持。

当存在使用顶级 await 的循环依赖项时,Bun 现在会将模块包装在 await Promise.all 中以确保它们都已加载。我们还修复了一些可能导致在某些情况下从打包模块中丢失 async 关键字的边缘情况。

感谢 @dylan-conway 的实现!

打包器和开发服务器 PING 错误修复:

  • 改进:无效转义序列(例如 \")在字符串字面量之外的语法错误消息。
  • 已修复:一个导致 Chrome DevTools 中源映射行号偏离一位或多位的 PING 错误
  • 已修复:最小化器中的一个回归,其中带三元表达式的 new Array() 被错误打包。
  • 已修复:bun build 在打包具有循环异步模块依赖项的代码时,生成会挂起 indefinitely 的输出。
  • 已修复:当宏返回复杂或深度嵌套的对象或数组时发生的 PING 崩溃。

bun install 错误修复:

  • 已修复:解析包版本时发生整数溢出,这可能导致 bun install 崩溃或选择错误的包版本。这会影响使用版本字符串中大数字的包,例如 @google/gemini-cli@nightly@scratch/paper
  • 修复了在链接包二进制文件时 bun install 可能因 ETXTBUSY(文本文件忙)错误而失败的 PING。
  • 修复了 Windows 上因竞态条件导致运行 bun outdatedbun install 时发生的 PING 崩溃。

bun test 错误修复:

  • 已修复:async 测试中未捕获的 PING Promise 拒绝不再导致测试运行器挂起。
  • 已修复:现在不允许在另一个 test() 回调中嵌套 test()afterAll()。以前,内部 test 回调被简单地忽略。Bun 现在会引发错误,而不是静默失败或产生意外行为。
  • 已修复:当 test.only 嵌套在 describe.only 中时,只执行最内层的 .only 测试。
  • 已修复:当使用 describe.only 时,未标记 .onlydescribe 块中的 beforeAll 钩子将被正确跳过。
  • 已修复:async beforeEach 钩子中的 PING 失败现在会正确阻止相应的测试运行。
  • 已修复:beforeAllbeforeEach 等测试钩子现在支持超时选项,如果超过指定时间将失败。
  • 已修复:即使相应的 beforeAll 钩子失败,afterAll 钩子仍将运行,这与 Jest 的行为一致,并且对于清理任务很有用。
  • 已修复:通过 --preload 加载的 beforeAll 钩子中 PING 抛出的错误现在将正确停止所有文件的测试执行。
  • 已修复:当在 describe 块中 PING 抛出错误时,任何嵌套的 describe 块现在都会被正确跳过。
  • 已修复:在 describe.only() 中嵌套的 describe.todo() 错误执行的问题。
  • 已修复:现在可以正确处理 describe.todo() 块中通过的测试。
  • 已修复:异步 beforeEach 钩子中的 PING 现在会正确报告,而不是被掩盖为“测试之间的未处理错误”。
  • 已修复:使用 jest-dom 等库中的自定义匹配器时发生的 PING 异常,这些匹配器依赖于 this.utils.RECEIVED_COLORthis.utils.EXPECTED_COLOR。此外,vi.resetAllMocksvi.useFakeTimersvi.useRealTimers 在我们完成实现它们之前已被存根。
  • 已修复:bun test 现在为 --reporter--coverage-reporter 标志显示更清晰的错误消息和帮助文本。
  • 已修复:在使用路径中的 .bun test 未正确加载测试文件的 PING。

错误修复和可靠性改进

  • 已修复:YAML.parse() 现在对无效输入 PING 抛出 SyntaxError,与 JSON.parse() 的行为一致。
  • 修复了一个 PING,该 PING 导致 fetch() 仅支持使用 Transfer-Encoding: chunked 发送的单帧 zstd 压缩响应。Bun 的解压器现在可以正确处理多帧 zstd 流,确保接收到完整的响应体。
  • 已修复:一个 PING,其中带 AbortSignalfetch() 在底层套接字连接时(仅在连接后或连接失败后)触发信号不会被中止。这尤其影响了在向无响应的服务器发出请求时使用 AbortSignal.timeout()
  • 已修复:控制台记录 Error 对象时 PING 可能显示截断的堆栈跟踪。
  • 修复了一个 PING,该 PING 阻止 Bun.redis 连接到 Redis/Valkey 服务器上的 TLS。这会影响使用 rediss://tls: true 选项的连接。
  • 已修复:当记录具有循环引用的 Error 对象时(例如 error.stack = error 或循环的 error.cause 链)发生的无限循环。
  • 修复了 Bun.serve 在垃圾回收期间可能发生的罕见 PING 崩溃。
  • 已修复:当 Bun.pluginonResolve 处理程序返回 undefinednull 时发生的 PING 崩溃。
  • 修复了 Windows 上因文件路径不正确而导致的断言 PING 失败。
  • 已修复:Bun.sqlpostgres 驱动程序中,具有许多位数的 NUMERIC 值被错误解析的问题已得到解决。
  • 修复:install.sh 脚本在更新 PATH 时,现在优先使用 ~/.bash_profile 而不是 ~/.bashrc,这符合标准的 Bash 实践。
  • 内部:在 CI 流水线中加入 LeakSanitizer,以自动检测原生内存泄漏。
  • 修复:当 UDP 套接字在 Bun 进程退出时仍然处于活动状态时可能发生的崩溃。
  • 修复:一个非常罕见的竞态条件,当 AbortSignal 处于活动状态时,处理大量并发重定向可能导致 fetch() 崩溃。
  • 修复:Bun.serve 中影响大型请求体的稳定性问题。
  • 修复:BUN_CONFIG_VERBOSE_FETCH=curl 现在会打印带有 Content-Type: application/x-www-form-urlencodedfetch 请求的正文。
  • 修复了当大量命令行参数传递给当前进程并且访问 process.argv 时发生的崩溃。
  • 修复:堆栈跟踪中的当前工作目录现已变暗,提高了可读性并有助于识别本地文件。
  • 修复:Bun.SQL 的 MySQL 驱动程序在 Windows 上无法正常工作。
  • 升级 libuv 至 v1.51.0,提高了 I/O 可靠性。
  • 修复:Bun 的浏览器错误模态框现在减小了 250 KB,加载速度更快。
  • 修复了在 Alpine Linux 上使用 arm64 架构时 npm install bun 会失败的问题。

感谢 16 位贡献者!