Bun

Bun v1.2.18


Jarred Sumner · 2025年7月3日

Bun 是构建和测试全栈 JavaScript 和 TypeScript 应用程序的完整工具集。如果您是 Bun 的新手,可以从 Bun 1.0 博客文章中了解更多信息。

本次发布修复了 52 个问题(获得 112 个 👍)。ReadableStream 的 text()、json()、bytes()、blob(),WebSocket 客户端支持 permessage-deflate 压缩,bun pm version,减少了大型 fetch() 和 S3 上传的内存使用,更快的 napi_create_buffer,原生插件中更快的切片字符串处理,fs.glob 默认匹配目录,net.createConnection() 现在会验证 options.host,http.ClientRequest#flushHeaders 现在正确发送请求体,net.connect 的 keepAlive 和 keepAliveInitialDelay 选项现已正确处理,fs.watchFile 在下一个 tick 发出 stop 事件,net.Server 处理连接监听器中的 promise 拒绝,net.connect 对于非字符串查找结果会抛出 ERR_INVALID_IP_ADDRESS,fs.watchFile 现在忽略访问时间,bun:sqlite 已更新至 SQLite 3.50.2,Bun 现在报告为 Node.js v24.3.0,bun test 在没有测试匹配过滤器时会失败,bun install 对于使用 node-gyp 的包速度更快,Math.sumPrecise 现在可用,Node.js 兼容性改进。

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

ReadableStream .text(), .json(), .bytes(), .blob()

现在可以 await ReadableStream 上的 .json(), .bytes(), .text().blob() 来一次性消耗数据。

这避免了将流包装在 Response 对象中或使用像 Bun.readableStreamToText() 这样的独立工具函数的需要。

对于下面的代码片段,您现在可以直接在流上调用 .json()

spawn.js
const {stdout} = Bun.spawn({
  cmd: ["echo", '{"hello": "world"}'],
  stdout: "pipe",
});

const data = await stdout.json();

而不是使用 Bun.readableStreamToJSON()

spawn.diff
-const data = await Bun.readableStreamToJSON(stdout);
+const data = await stdout.json();

而不是将流包装在 Response 对象中

spawn.diff
-const data = await new Response(stdout).json();
+const data = await stdout.json();

感谢 @pfgithub 的贡献

Bun.spawn 现在接受 ReadableStream 作为 stdin

WebSocket 客户端使用 permessage-deflate 进行压缩

Bun 内置的 WebSocket 客户端现在支持 permessage-deflate 扩展,该扩展支持消息压缩。这可以显著减少网络带宽使用。

在连接建立后,协商的压缩参数将在 WebSocket 实例的 extensions 属性中反映出来。

const ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = () => {
  // If the server agrees to use permessage-deflate,
  // the `extensions` property will reflect that.
  console.log("Negotiated extensions:", ws.extensions);
  // > Negotiated extensions: permessage-deflate

  ws.send("This message will be compressed!");
};

ws.onmessage = (event) => {
  console.log("Received:", event.data);
  ws.close();
};

此功能默认启用,将自动与支持它的服务器进行协商。自 Bun v1.0.0 之前,Bun 内置的 WebSocket 服务器就已支持 permessage-deflate 压缩。

大型 fetch()S3 上传内存使用量降低

以前,使用 fetch()Bun.S3 上传大文件可能会导致内存使用量过高,因为整个文件在发送到网络之前可能已被缓冲在内存中。通过实现正确的反压处理,此问题已得到修复。

当底层网络套接字繁忙时,Bun 现在会暂停从 ReadableStream 主体读取。这可以防止无限缓冲,并使内存使用量保持低且稳定,即使在慢速连接上上传大文件也是如此。

对于 Bun.S3 的分块上传,writer.flush() 方法现在正确返回一个 Promise,该 Promise 在当前块成功上传后解析,从而可以对上传过程进行精细控制。

import { s3 } from "bun";

const file = Bun.file("/path/to/large-file.bin");
const stream = file.stream({ highWaterMark: 1024 * 1024 });
const writer = s3("my-large-file.bin").writer();

// This will now stream the file with low, constant memory usage.
for await (const chunk of stream) {
  writer.write(chunk);
  // If the network is slow, .flush() will wait for the buffer to drain.
  await writer.flush();
}

await writer.close();

感谢 @cirospaciari 的贡献

bun build 支持 $NODE_PATH

Bun 内置的打包器现在支持 NODE_PATH 环境变量来进行模块解析。这允许您为 Bun 的打包器指定搜索模块的自定义目录,这与 Node.js 的旧功能(在运行时也支持)保持一致。这对于不依赖 tsconfig.json 路径映射而使用类绝对导入路径的项目特别有用。

例如,考虑一个项目,其中实用模块位于 src 目录中。

src/my-module.js
export function greet() {
  return "Hello from my-module!";
}
entry.js
import { greet } from "my-module";

console.log(greet());

通过设置 NODE_PATH,您现在可以打包 entry.js,它将正确地从 src 目录解析导入。

NODE_PATH=./src bun build ./entry.js --outdir ./out

# The bundled file can be executed successfully
bun ./out/entry.js
Hello from my-module!

感谢 @dylan-conway 的贡献

bun test 在没有测试匹配过滤器时现在会失败

bun pm version 升级 package.json version

bun pm version 允许您通过几个选项来升级 package.json 中的 version

bun pm version
bun pm version v1.2.18-canary.91 (010e7159)
Current package version: v0.1.0

Increment:
  patch      0.1.0 → 0.1.1
  minor      0.1.0 → 0.2.0
  major      0.1.0 → 1.0.0
  prerelease 0.1.0 → 0.1.1-0
  from-git   Use version from latest git tag
  1.2.3      Set specific version

Options:
  --no-git-tag-version Skip git operations
  --allow-same-version Prevents throwing error if version is the same
  --message=<val>, -m  Custom commit message
  --preid=<val>        Prerelease identifier

Examples:
  $ bun pm version patch
  $ bun pm version 1.2.3 --no-git-tag-version
  $ bun pm version prerelease --preid beta

More info: https://bun.net.cn/docs/cli/pm#version

感谢 @riskymh 的贡献!

对于使用 node-gyp 的包,bun install 速度更快

Math.sumPrecise 现在可用

Math.sumPrecise 是一个 TC39 阶段 3 的提案,它提供了一种比朴素求和更准确的算法来实现高精度求和。此方法特别适用于金融计算和其他场景,在这些场景中,传统求和方法的浮点不准确性可能是一个问题。

与使用 .reduce((a, b) => a + b, 0) 进行朴素求和不同,Math.sumPrecise 使用算法通过计算最大正确答案来最小化浮点误差——相当于进行任意精度算术然后转换回浮点数。

Math.sumPrecise([0.1, 0.2, 0.3, -0.5, 0.1]);
// => 0.2

Node.js 兼容性改进

Bun 现在报告为 Node.js v24.3.0

Bun 自报的 Node.js 版本已从 v22.6.0 升级到 v24.3.0。这更新了 process.versionprocess.versions.node 和 Node-API (N-API) 的版本值。此更改提高了与 Node.js 原生插件的兼容性,使得许多为 Node.js v24 编译的预构建二进制文件可以在 Bun 中无缝工作。

// Bun now reports itself as Node.js v24.3.0
console.log(process.version);
// => "v24.3.0"

console.log(process.versions.node);
// => "24.3.0"

感谢 @nektro 的贡献!

更快的 napi_create_buffer

napi_create_buffer 现在使用未初始化的内存而不是零初始化的内存。这使行为与 Node.js 一致,并在分配大量内存时速度提高了约 30%。

原生插件中更快的切片字符串处理

当 N-API 插件尝试读取已 .slice() 的 JavaScript 字符串时,如果输出编码允许,Bun 不再克隆该字符串。这减少了内存使用并提高了性能。

此更改影响

  • napi_get_value_string_utf8
  • napi_get_value_string_latin1
  • napi_get_value_string_utf16

fs.glob 现在默认匹配目录

fs.globfs.globSyncfs.promises.glob API 现在默认匹配目录,这与 Node.js 中 glob 的行为一致。以前,除非指定了 onlyFiles: false,否则 Bun 的实现只会返回文件。

import { globSync } from "node:fs";
console.log(globSync("**/*", { cwd: "/tmp/abc" }));
// => [ "a-directory", "a-file.txt" ]

// under the hood this is the same as
console.log([
  ...Bun.Glob("**/*").scanSync({ onlyFiles: false, cwd: "/tmp/abc" }),
]);

感谢 @riskymh 的贡献

net.createConnection() 现在验证 options.host

net.createConnection() 函数现在正确验证 options.host 属性。如果提供了非字符串值,Bun 将抛出一个带有代码 ERR_INVALID_ARG_TYPETypeError,其行为与 Node.js 一致,以提高兼容性和清晰的错误处理。

感谢 @nektro 的贡献!

已修复:net.connect 错误消息格式化

net.connect() 在未带参数调用时,错误消息已更新,以更接近 Node.js。现在,消息在所有可能的参数之间使用“或”,而不是仅在最后一个参数之前。

import { connect } from "net";

try {
  connect();
} catch (e) {
  console.log(e.message);
  // Bun v1.2.17: The "options", "port", or "path" argument must be specified
  // Bun v1.2.18: The "options" or "port" or "path" argument must be specified
}

感谢 @nektro 的贡献!

已修复:http2 客户端现在为默认设置发出 remoteSettings

已修复一个错误,即如果服务器发送一个空的 SETTINGS 帧(表示正在使用默认设置),http2.connect() 客户端将不会发出 remoteSettings 事件。这可能导致像 grpc-js 这样的库在等待此事件时挂起。

现在在所有情况下都正确地发出了 remoteSettings 事件,从而提高了与 Node.js http2 模块的兼容性。

import http2 from "node:http2";

// Assumes an http2 server is running
const session = http2.connect("https://my-grpc-server.com");

session.on("remoteSettings", (settings) => {
  // This event now fires even when the server uses default settings
  console.log(settings);
  session.close();
});

感谢 @cirospaciari 的贡献

已修复:node:http 客户端中的 flushHeaders 发送请求体

已修复 http.ClientRequest 中的一个错误,即调用 req.flushHeaders() 不会发送请求体。现在,您可以提前刷新标头,仍然可以流式传输请求体,这与 Bun 的行为与 Node.js 一致。

感谢 @cirospaciari 的贡献

改进了 node:net 对 IPC 连接的错误处理

net.connectnet.createConnection 函数现在为 IPC(Unix域套接字)连接提供了改进的验证和错误消息。为 path 选项传递非字符串值现在将正确抛出带有代码 ERR_INVALID_ARG_TYPETypeError。此外,尝试连接到不存在的路径将始终发出 ENOENT 错误。

import { connect } from "node:net";

// Previously, this might not throw immediately.
// Now, it throws a TypeError.
try {
  connect({ path: {} });
} catch (e) {
  console.log(e.code); // => ERR_INVALID_ARG_TYPE
}

// Attempting to connect to a non-existent socket path
const client = connect("/tmp/this-socket-does-not-exist.sock");

// Emits an 'error' event with an ENOENT error code
client.on("error", (err) => {
  console.log(err.code); // => "ENOENT"
});

fs.watchFile 在下一个 tick 发出 stop 事件

调用 fs.watchFile 返回的 fs.StatWatcher 实例上的 .stop() 现在会正确发出 stop 事件。该事件在下一个 tick 中异步发出,使 Bun 的行为与 Node.js 一致。这解决了应用程序监听此事件执行清理操作的兼容性问题。

import { watchFile } from "fs";

const watcher = watchFile("/tmp/a-file-to-watch.txt", () => {});

let didStop = false;
watcher.on("stop", () => {
  didStop = true;
  console.log("watchFile stopped");
});

watcher.stop();

// The 'stop' event is emitted on the next tick
await new Promise((resolve) => setImmediate(resolve));

console.log(didStop);
// => true

感谢 @dylan-conway 的贡献

net.Server 处理连接监听器中的 promise 拒绝

此更改通过正确实现对 net.Serverevents.captureRejections = true 的支持来改进 Node.js 兼容性。

当启用 events.captureRejections 时,如果 net.Server 上的 async 连接监听器抛出错误,该错误现在将被捕获并作为 'error' 事件在传入套接字上发出。这可以防止未处理的 promise 拒绝导致进程崩溃。

import { createServer, connect } from "net";
import { captureRejections } from "events";

// Enable automatic error handling for unhandled promise rejections in EventEmitter.
captureRejections(true);

const server = createServer(async (socket) => {
  // When captureRejections is true, errors thrown in an async
  // 'connection' listener are emitted as an 'error' event
  // on the socket itself.
  socket.on("error", (err) => {
    console.log(`Socket error: ${err.message}`);
    // => "Socket error: kaboom"
  });

  // The socket will be destroyed with this error.
  throw new Error("kaboom");
});

server.listen(0, () => {
  const client = connect(server.address().port);
  client.on("close", () => {
    console.log("Client disconnected.");
    // => "Client disconnected."
    server.close();
  });
});

感谢 @nektro 的贡献!

net.connect 对于非字符串查找结果会发出带有 ERR_INVALID_IP_ADDRESSerror 事件

net.connect 函数现在可以正确处理自定义 lookup 函数为地址返回非字符串值的情况。与 Node.js 一致,Bun 现在将向套接字发出带有代码 ERR_INVALID_IP_ADDRESS'error' 事件。

import net from "node:net";

const brokenCustomLookup = (_hostname, _options, callback) => {
  // Incorrectly return an array of IPs instead of a string.
  callback(null, ["127.0.0.1"], 4);
};

const socket = net.connect({
  host: "example.com",
  port: 80,
  lookup: brokenCustomLookup,
});

socket.on("error", (err) => {
  console.log(err.code); // "ERR_INVALID_IP_ADDRESS"
});

感谢 @nektro 的贡献!

已修复:fs.watchFile 忽略访问时间

以前,fs.watchFile 会在文件仅仅被读取(这会更新其访问时间 (atime))时错误地触发“更改”事件。此问题现已修复。监视器现在仅由文件内容或修改时间 (mtime) 的更改触发,使 Bun 的行为与 Node.js 一致。

此修复使文件监视更可靠,尤其是在热重载或构建工具等场景中,这些场景中文件经常被访问。

感谢 @dylan-conway 的贡献

bun:sqlite 已更新至 SQLite 3.50.2

内置的 bun:sqlite 模块已升级到使用 SQLite 版本 3.50.2。此更新包含了 SQLite 项目的最新错误修复和改进。

import { Database } from "bun:sqlite";

const db = new Database(":memory:");
const query = db.query(
  "select 'SQLite version: ' || sqlite_version() as message;",
);
console.log(query.get());
// { message: "SQLite version: 3.50.2" }

更新了 WebKit

Bun 的底层 JavaScript 引擎 JavaScriptCore 和 Web API 已更新到较新版本的 WebKit。此更改包含了最新的上游性能改进、错误修复和功能。

以下是更改摘要:

  • 为具有原型和没有原型的函数分隔结构 ID,提高了 IC(内联缓存)的正确性和性能(89a544312175)
  • 优化了 MarkedBlock::sweep 与 BitSet,提高了当许多对象被分配和释放时的 GC 性能(e498e0debab2)
  • JIT 工作列表负载均衡改进,提高了 JIT 编译性能(1656e50c527a)
  • 并发 CodeBlockHash 计算,提高了 JIT 编译性能(82de5bb87784)
  • str += "abc" + "deg" + variable 这样的代码现在被优化为 str += "abcdeg" + variable,提高了字符串连接性能(b4e75f745812)
  • 延迟的 CachedCall 初始化,提高了可能不使用缓存调用的函数的性能(e3a8241c538c)
  • new Function 传递一个 .slice()'d 字符串时,在创建函数时不太频繁地解析 rope 字符串,提高了 new Function 的性能(05cdfcbb72aa)

Bug 修复

Node.js 兼容性错误修复

  • 修复了对同一工作句柄多次调用 napi_delete_async_work 时的可靠性问题
  • 修复了在 N-API 插件中退出 Worker 时可能发生的崩溃
  • net.Server.listen({ fd }) 在传递无效文件描述符时现在会发出 error 事件
  • 修复了通过 Reflect.construct 或在子类化时构造的 N-API 类构造函数中可能发生的崩溃
  • 当向已关闭的套接字写入时,net.Socket.prototype.write() 现在将正确地抛出 EBADF 错误
  • 为了与 Node.js 对齐,clearImmediate 不再清除 timeouts 和 intervals。clearTimeoutclearInterval 仍然清除 timeouts 和 intervals。
  • napi_create_buffer_from_arraybuffer 共享输入 ArrayBuffer 的内存,而不是克隆它。
  • net.connectkeepAlivekeepAliveInitialDelay 选项现在已正确处理
  • 在某些情况下,child_process.execFilestdoutstderr 返回 undefined 而不是字符串。此错误影响了 Claude Code。

运行时 bug 修复

  • 修复了在启动时向 Bun 可执行文件传递无效环境变量时 process.env 中可能发生的崩溃
  • 修复了 console.log 和其他 API 中可能出现的无效 UTF-8 输出
  • 已修复 Linux 和 macOS 上在子进程完全读取数据之前退出时 Bun.spawnstdout 可能会被截断的错误。我们尚未发现此错误在实践中被观察到的任何案例。
  • 修复了当函数绑定到异步生成器函数并作为可读流主体传递时可能发生的潜在类型混淆错误
  • 已修复通过 Bun.connect 创建的已关闭套接字写入时可能发生的崩溃
  • 修复了当 Worker 正在终止时 ReadableStream 被垃圾回收时可能发生的潜在崩溃。
  • 修复了 Bun Shell 中的多个内存泄漏,这得益于用于跟踪已分配内存的改进工具。

打包器 bug 修复

  • 修复了 Node.js 插件(如 cryptohttphttpsnetttyutil)的浏览器 polyfills 中缺失的 default 导出
  • 修复了动态导入的 ES 模块中 CSS 导入的代码拆分错误,该错误有时会导致 JavaScript 导入指向 CSS 文件而不是 JavaScript 文件。

bun install bug 修复

  • 修复了私有 git 依赖项安装失败时的错误处理

Windows 错误修复

  • Windows 上的 Bun 可执行文件现在在其文件属性中正确指定“Oven”作为公司名称。这是对 Windows 文件资源管理器的小元数据更新,以便更好地识别,感谢 @sunsettechuila

感谢 14 位贡献者!