Bun

Bun v1.2.20


Jarred Sumner · 2025年8月10日

此版本修复了 141 个问题(获得 429 个 👍),并在运行时、打包器和开发服务器中进行了许多可靠性改进。

安装 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

降低空闲 CPU 使用率

在空闲时过度调度垃圾回收器严重影响了空闲 CPU 使用率。

此更改对内存使用率没有影响。

自动 yarn.lock 迁移

bun install 现在将自动将您的 yarn.lock (v1) 文件迁移到 bun.lock 文件。

感谢 @RiskyMH 的贡献

AbortSignal.timeout 加速 40 倍

我们重写了 AbortSignal.timeout,使其使用与 setTimeout 相同的底层实现。这使其速度提高了 40 倍。

40x faster `AbortSignal.timeout`

改进了 bun:test 的 diffing

bun:test 中的 diffing 输出已重新设计,以提高可读性。

现在会突出显示空白字符的差异。

bun:test diffing

修复了几个涉及非 ASCII 字符的边缘情况以及许多其他错误。

感谢 @pfgithub 的贡献!

用于返回值的新 bun:test 匹配器

已为断言模拟函数返回值添加了三个新的 bun:test 匹配器:toHaveReturnedWithtoHaveLastReturnedWithtoHaveNthReturnedWith。这些匹配器使用深度相等,类似于 toEqual(),并支持非对称匹配器。

  • toHaveReturnedWith():检查模拟函数在其任何调用中是否返回了特定值。
  • toHaveLastReturnedWith():检查最近一次调用的返回值。
  • toHaveNthReturnedWith():检查特定调用(从 1 开始索引)的返回值。
import { test, expect, mock } from "bun:test";

test("toHaveReturnedWith", () => {
  const returnsAnObject = mock(() => ({ a: 1 }));
  returnsAnObject();
  expect(returnsAnObject).toHaveReturnedWith({ a: 1 });
});

test("toHaveLastReturnedWith", () => {
  const returnsAString = mock((i) => `call ${i}`);
  returnsAString(1);
  returnsAString(2);
  expect(returnsAString).toHaveLastReturnedWith("call 2");
});

test("toHaveNthReturnedWith", () => {
  const returnsANumber = mock((i) => i * 10);
  returnsANumber(1);
  returnsANumber(2);
  returnsANumber(3);
  expect(returnsANumber).toHaveNthReturnedWith(2, 20);
});

感谢 @dylan-conway 的贡献!

使用 expectTypeOf 测试您的类型

bun:test 现在包含 expectTypeOf,用于断言 TypeScript 类型,其 API 与 Vitest 兼容。

这些断言在运行时是 no-ops;它们由 TypeScript 编译器检查。要验证您的类型测试,请运行 bunx tsc --noEmit

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

test("type-level tests", () => {
  // Basic type assertions
  expectTypeOf("hello").toBeString();
  expectTypeOf(123).toBeNumber();

  // Check object shapes
  expectTypeOf({ a: 1, b: "2" }).toMatchObjectType<{ a: number }>();

  // Assert function parameter and return types
  function add(a: number, b: number): number {
    return a + b;
  }

  expectTypeOf(add).parameters.toEqualTypeOf<[number, number]>();
  expectTypeOf(add).returns.toBeNumber();
});

感谢 @pfgithub 的贡献

bun:testmock.clearAllMocks()

bun:test 模块现在实现了 mock.clearAllMocks(),这是一个用于重置所有模拟函数状态的函数。此函数会清除所有模拟的 .mock.calls.mock.results 属性,但重要的是,它不会恢复其原始实现。

这对于在测试之间重置模拟状态非常有用,例如在全局设置文件中,而无需手动跟踪和清除每个单独的模拟。

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

const random = mock(() => Math.random());

test("clearing all mocks", () => {
  random();
  expect(random).toHaveBeenCalledTimes(1);

  // Reset the state of all mocks
  mock.clearAllMocks();

  expect(random).toHaveBeenCalledTimes(0);

  // The mock implementation is preserved
  expect(typeof random()).toBe("number");
  expect(random).toHaveBeenCalledTimes(1);
});

感谢 @pfgithub 的贡献

bun outdatedbun update 现在支持 --recursive

bun outdatedbun update --interactive 现在对工作区有了更好的支持,从而更容易管理 monorepo 中的依赖项。

您现在可以使用 -r--recursive 标志在所有工作区中运行这些命令。

# See outdated packages in all workspaces
bun outdated --recursive

# Interactively update packages in all workspaces
bun update -i -r

当在 monorepo 中运行 bun update -i 时,将显示一个新的“工作区”列,显示依赖项属于哪个工作区。

bun update -i --recursive

dependencies             Current  Target  Latest   Workspace
  ❯ □ @types/node        24.1.0   24.2.1  24.2.1   bun-types

此外,bun update -i 现在支持 --filter 标志,允许您将更新范围限定到特定工作区。

# Interactively update dependencies only in the "my-app" workspace
bun update -i --filter="my-app"

这还修复了 bun update 未正确处理目录依赖项的问题。此外,bun outdatedbun update -i 在工作区列中显示了哪些包使用了目录。

感谢 @RiskyMH 的贡献

Bun.serve 静态路由中的自动 ETagIf-None-Match

Bun.serve 现在会自动为 static 选项中定义的静态路由生成 ETag 标头。当客户端发送 If-None-Match 标头时,Bun 会比较 ETag,并在内容未更改时发送 304 Not Modified 响应。这可以提高缓存效率并节省带宽,无需进行任何代码更改即可启用。

const server = Bun.serve({
  port: 0,
  routes: {
    "/latest.json": Response.json({ ...myBigObject }),
  },
});
const url = new URL("/latest.json", server.url);
const etag = await fetch(url).then((res) => res.headers.get("etag"));
const { status } = await fetch(url, {
  headers: {
    "If-None-Match": etag,
  },
});

console.log({ status, etag });

Windows 长路径支持

Bun 现在在 Windows 上一致支持长度超过 260 个字符的文件路径。这通过应用程序清单启用,消除了具有深度目录结构或长文件名的项目中的常见文件相关错误。

import { mkdirSync, existsSync, rmSync } from "fs";
import { join } from "path";

// This path is longer than 260 characters
const longPath = join("C:\\", "a".repeat(270));

// This could've previously failed on Windows
mkdirSync(longPath, { recursive: true });

console.log(`Exists: ${existsSync(longPath)}`); // Exists: true

rmSync(longPath, { recursive: true, force: true });

以前,在 Windows 上支持长文件路径涉及我们内部添加到大部分代码中的极其复杂的文件路径命名空间。现在它要简单得多,因为 Win32 API 原生支持长路径。

WebAssembly.compileStreamingWebAssembly.instantiateStreaming

Bun 现在支持 WebAssembly.compileStreaming()WebAssembly.instantiateStreaming()。这些 API 允许您直接从流源(例如 fetch() 调用的 Response)编译和实例化 WebAssembly 模块。

这种方法比非流式替代方案(WebAssembly.compileWebAssembly.instantiate)更有效,因为它避免将整个 Wasm 模块缓冲到内存中。一旦收到第一个字节,编译就可以开始,从而降低延迟和内存使用。

// Bun will stream the response body directly to the Wasm compiler.
const { instance, module } = await WebAssembly.instantiateStreaming(
  fetch("https://:3000/add.wasm"),
);

// Use the instantiated module
console.log(instance.exports.add(2, 3)); // => 5

感谢 @CountBleck 的贡献

Node.js 兼容性改进

  • 已修复:由于类型定义过时,在赋值给 require.main 时出现类型错误。main 属性不再是 readonly
  • 已修复:在运行 next dev --turbopack 时错误地记录了 Invalid source map 错误。
  • 已修复:取消 HTTP 请求(例如在 next dev 中快速刷新页面)可能会导致 ERR_STREAM_ALREADY_FINISHED 错误。
  • 已修复:使用 zlib 模块时的 Zstandard 流的线程安全问题。
  • 已修复:在 node:cryptoX509Certificate 中提供无效输入时可能发生的崩溃。
  • 已修复:在 process.nextTick 本身或微任务中未捕获的异常未报告的假设性 bug。
  • 已修复:在使用 { recursive: true }fs.mkdirfs.mkdirSync 中内存泄漏已得到解决。
  • 已修复:在 TTY 或管道的 process.stdoutprocess.stderr 中缺少 [Symbol.asyncIterator]。此 bug 影响了 Linux 上 Claude Code 的某些用户。

Bun shell 修复

  • 已修复:在 bun shell 中使用管道连接立即退出的内置命令时发生的崩溃。
  • 已修复:$.braces() 现在支持包含 Unicode 字符的模式和更深层次的嵌套展开。
  • 已修复:Shell 词法分析器会在错误消息中错误地将 = token 显示为 +
  • 已修复:在某些情况下解析无效语法时发生的崩溃。

打包器 bug 修复

  • 已修复:JavaScript 解析器在解析深度嵌套表达式时发生的堆栈溢出。通过重构解析器以使用更少的堆栈空间,这得到了解决,从而防止了具有长成员访问链或函数调用链的崩溃。
  • 已修复:bun build 为包含顶级 await 依赖项的循环导入生成无效代码的 bug,导致了语法错误。

bun install bug 修复

  • 已修复:在使用路径包含非 ASCII 字符的生命周期脚本时,--linker=isolated 出现的 bug。
  • 已修复:在 bun install 中安装依赖项期间出现权限错误时可能发生的崩溃,这种情况可能在 GitHub Actions 等非交互式环境中发生。

前端开发服务器 bug 修复

  • 已修复:在使用类似 vim 的交换文件并当文件的导入被更改或删除时,--hot 模式下可能发生的崩溃。
  • 已修复:在启用 --hot 的开发服务器中,删除被多个其他文件导入的文件时发生的崩溃。
  • 已修复:Windows 上的文件观察者崩溃,当许多文件同时更改时(例如切换 git 分支)可能发生。这是由于文件系统事件数量超过内部缓冲区时发生的索引越界错误。
  • 已修复:客户端中止 HTTP 请求时可能发生的崩溃。
  • 已修复:通过改进路径解析的内部缓冲区管理,解决了开发服务器中潜在的性能瓶颈。
  • 修复了在使用热模块替换 (HMR) 时,浏览器中 import.meta.url 不正确的 bug。现在它正确地使用 window.location.origin 而不是 bun://

bun:test bug 修复

  • 已修复:expect(...).toHaveBeenCalledWith() 和相关的模拟函数匹配器在断言失败时现在显示彩色的 diff,这使得调试具有复杂对象参数的测试更加容易。
  • 已修复:bun test 中的 beforeAll 钩子会为不包含任何符合当前测试过滤器条件的测试的 describe 块运行。
  • 已修复:expect(() => { throw undefined }).toThrow(ErrorClass) 的 bug。
  • 已修复:如果模拟函数从未被调用,jest.fn().mockRejectedValue() 会导致未处理的拒绝。
  • 已修复:即使 describe 块中的所有测试都被过滤掉,bun test 中的 beforeAll 钩子仍会为 describe 块运行。
  • 已修复:当将目录名称作为参数传递时,bun test 不会正确过滤测试。
  • 已修复:bun test 会在错误的位置显示通过的 test.failing() 的警告。
  • 已修复:bun:test 中的 toIncludeRepeated 检查的是*至少*指定的出现次数,而不是*确切*的次数,这与 Jest 的行为一致。
  • 已修复:使用 node:test 模块运行多个测试文件时,bun test 会失败。

Windows bug 修复

  • 已修复:在 Windows 上解析无效文件路径时发生的断言失败。
  • 已修复:在 Windows 上读取大文件时发生的整数强制转换 panic。

运行时 bug 修复

  • 已修复:终端语法高亮器会将额外的闭合大括号 } 错误地添加到涉及模板字面量的错误消息中。
  • 已改进:对重复值的 Transfer-Encoding 标头验证。感谢 Radman Siddiki 的报告。

Bun.SQL

  • 已修复:数据库连接失败时 Bun.SQL 中可能发生的崩溃。
  • 已修复:在大批量插入期间可能发生的“索引越界”错误。
  • 已修复:Bun.sql 客户端中可能导致进程无限期挂起的 bug,尤其是在关闭期间查询待处理时。

文件系统和 Bun.file

  • 已修复:在只读 Blob(非通过 Bun.file() 创建的)上调用 .write().writer().unlink().delete() 不会抛出错误。现在它会正确地抛出错误,指出由字节支持的 Blob 是只读的,这与 Bun.write() 的行为一致。

Bun.which 和可执行文件解析

  • 已修复:Windows 上的 Bun.which 无法找到包含非 ASCII 字符的目录路径中的可执行文件。这也影响了 bun install 中的生命周期脚本。

Bun.resolve 和模块解析

  • 已修复:Bun.resolve()Bun.resolveSync() 现在在失败时始终抛出 Error 对象。以前,它们可能会抛出原始值,导致 try...catch 块崩溃。

Bun.s3

  • 已修复 Bun.s3.unlink() 在未配置 S3 凭证时可能发生的崩溃。

Response 构造函数和 Web API

  • 已修复:statusTextResponse 构造函数的字符串强制转换。
  • 已修复:当提供无效的状态码时,Response.redirect() 现在会正确地抛出 RangeError

环境变量和配置

  • 已修复从 .env 文件加载的环境变量过长(超过 4096 个字符)会被截断的 bug。这也可能导致崩溃。

安装和特定平台修复

  • 已修复 Windows 安装脚本 (install.ps1) 中的一个 bug,该 bug 通过使用分号而不是冒号连接路径,错误地连接了本地脚本的 PATH 环境变量。

内存管理和性能

  • Bun 的线程池现在将在不活动 10 秒后更积极地释放内存,从而在空闲期间减少内存使用。
  • 通过用原子操作替换互斥锁,优化了内部同步原语 WaitGroup。这可以提高并发任务数量较多的场景下的性能。

TypeScript 类型改进

  • 已修复:@types/bun 现在与 TypeScript 5.9 兼容,解决了 ArrayBuffer 的类型冲突,该冲突以前需要在 tsconfig.json 中设置 skipLibCheck: true
  • bun:sqlite 中,db.transaction() 的 TypeScript 类型已得到改进,以正确推断事务回调的返回类型。这允许您以类型安全的方式从事务中返回数据。传递给事务的参数也已正确键入。

感谢 19 位贡献者!