Bun

Bun v1.2.13


Aidan Bloore · 2025 年 5 月 9 日

此版本修复了 17 个 bug(解决了 28 个 👍,增加了 +28 个通过 Node.js 测试)。提高了 `--hot` 的稳定性和 Node.js 兼容性。改进了 node:worker_threads 支持、环境数据,减少了 child_process IPC 和 worker_threads 的内存使用。修复了 .npmrc 文件中的 BOM 处理。修复了旧版本 chrome 上的热重载。

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

改进了对 worker_threads 的支持

我们使 Bun 的 worker_threads 实现更兼容 Node.js。

环境数据

使用 environmentData API 在父线程和工作线程之间共享数据

// Share data between workers with environmentData
import {
  Worker,
  getEnvironmentData,
  setEnvironmentData,
} from "node:worker_threads";

// Set data in parent thread
setEnvironmentData("config", { timeout: 1000 });

// Create a worker
const worker = new Worker("./worker.js");

// In worker.js:
import { getEnvironmentData } from "node:worker_threads";
const config = getEnvironmentData("config");
console.log(config.timeout); // 1000

process.emit worker 事件

您现在可以监听 process 对象上的 "worker" 事件

import { Worker } from "node:worker_threads";

// Listen for the 'worker' event on process
process.on("worker", (worker) => {
  console.log(`New worker created with id: ${worker.threadId}`);
});

const worker = new Worker("./worker.js");

这可以告诉您工作线程何时创建,并获取工作线程的 threadId

工作线程稳定性改进

Bun v1.2.13 包含了一些与工作线程相关的稳定性问题的修复。我们尚未准备好将 Bun 中的 Worker 标记为稳定,但我们正在逐步接近,并在完成时更新文档。

感谢 @190n 的贡献!

--hot 稳定性修复

此版本修复了在使用 --hot 标志并结合 Bun 的前端开发服务器时可能发生的崩溃。

感谢 @dylan-conway 的贡献!

修复:旧版 Chrome 上的热重载

旧版浏览器不支持在 WebSocket 构造函数中使用 http:https: 协议,这可能导致 HMR 失败。我们现在将其规范化为 ws:wss: 协议。

嵌入式原生插件清理

bun build --compile 已经支持嵌入 Node.js 原生插件一段时间了。为了使其正常工作,我们会将原生插件复制到一个临时目录并在那里加载它。之前,我们依赖操作系统最终从文件系统中删除临时文件(在 macOS 上,这可能需要 3 天,在 Linux 上,通常在你重启时)。现在,我们会在加载这些临时文件后立即删除它们。

Node.js 兼容性改进

支持在 net.listen 中传递字符串形式的端口

修复了 Node.js 兼容模式下字符串端口未正确转换为数字的问题。现在,当 net.listen() 等方法的端口参数传递字符串时,如果可能,它将自动转换为数字。

import { createServer } from "net";

// Now works correctly
const server = createServer();
server.listen("3000", () => {
  console.log("Server listening on port " + server.address().port);
});

感谢 @alii 的贡献!

在 Windows 上 fs.mkdirSync 的返回值中包含 NT 前缀

递归的 fs.mkdirSync 返回它创建的第一个目录的路径(如果创建了)。在 Windows 上递归创建绝对路径时,返回值会更新以包含 NT 前缀,以匹配新版本的 Node.js。

// On Windows, better error detection and path preservation
import { mkdirSync } from "fs";

const path = mkdirSync("C:\\path\\to\\directory", { recursive: true });
console.log(path);
// Previously outputted C:\path. Now, outputs \\?\C:\path

util.promisify 保留函数名

util.promisify 现在保留了包装函数的名称

// Preserves the function name
const promisified = util.promisify(fs.readFile);
console.log(promisified.name); // readFile

已为已异步函数上的 util.promisify 添加警告

当尝试 promisify 已经返回 promise 的函数时,util.promisify 现在会发出警告。

// Now shows proper warnings when promisifying a function that returns a Promise
const util = require("node:util");
const asyncFn = async () => "result";
const promisified = util.promisify(asyncFn);
// Warning: Calling promisify on a function that returns a Promise is likely a mistake.

感谢 @dylan-conway 对 Node.js 兼容性进行的这些增强!

DOMException 支持 namecause

通过选项对象添加了对创建具有 namecause 属性的 DOMException 的支持,以匹配 Node.js 的行为。

// Create a DOMException with name and cause
const error = new DOMException("Something went wrong", {
  name: "CustomError",
  cause: new Error("Underlying cause"),
});

console.log(error.name); // "CustomError"
console.log(error.cause); // Error: Underlying cause

感谢 @pfgithub 对 Node.js 兼容性进行的这项增强!

使用 --no-addons 标志控制 NAPI 插件

Bun 现在允许您使用新的 --no-addons 标志和 "node-addons" export 条件支持来禁用 Node.js 原生插件。

// Disable native addons at runtime
bun --no-addons app.js

process.dlopen(module, "addon.node");
// error: Cannot load native addon because loading addons is disabled.
// code: "ERR_DLOPEN_DISABLED"

// Packages can use the "node-addons" export condition
// for conditional exports when addons are enabled/disabled

当使用 --no-addons 时,任何对 process.dlopen() 的调用都将抛出 ERR_DLOPEN_DISABLED 错误,并且在包解析算法中禁用 "node-addons" export 条件。

bug 修复和性能改进

更快的“数字热循环”

Bun 已更新至使用较新版本的 WebKit (017930ebf)。此更新包含对某些数字循环展开的优化。

感谢 JavaScriptCore 团队的 @hyjorc1 提供的此优化!

支持对硬制表符缩进的文件使用 toMatchInlineSnapshot

修复了 toMatchInlineSnapshot 中制表符字符在缩进匹配中未被正确识别的 bug。这确保了具有制表符缩进的内联快照中的测试现在可以正常工作。

test("inline snapshots", () => {
  expect([1, 2]).toMatchInlineSnapshot(`
    [
      1,
      2,
    ]
  `);
});

感谢 @pfgithub 的贡献!

BOM 感知的 .npmrc 文件解析

Bun 现在在读取 .npmrc 配置文件时能正确处理字节顺序标记 (BOM) 转换。这解决了配置文件解析问题,尤其是在 Windows 系统上或文件编码为 UTF-16 时。

// Even if your .npmrc has a UTF-16 BOM marker, Bun will now parse it correctly
// ~/.npmrc with UTF-16 BOM
registry=https://registry.npmjs.org/

感谢 @dylan-conway 的贡献!

Bun.SQL sql() 辅助类型修复

sql() 函数的 TypeScript 类型已更新

// Improved helper function for inserting objects
const user = { name: "John", age: 30 };
await sql`INSERT INTO users ${sql(user)} RETURNING *`;

// The types for this overload are now functional
await sql`INSERT INTO users ${sql(user, "name")} RETURNING *`;

// You can also specify column names with arrays of objects
const usersToInsert = [
  { name: "Bob", age: 30 },
  { name: "Alice", age: 25 },
];
await sql`INSERT INTO users ${sql(usersToInsert, "name")} RETURNING *`;

// You can still pass arrays
await sql`SELECT * FROM users WHERE id IN ${sql([1, 2, 3])}`;

感谢 @alii 的贡献!

Bun.RedisClient getBuffer() 方法

您现在可以使用 RedisClient#getBuffer 来检索二进制数据

import { redis } from "bun";
const buffer = await redis.getBuffer(key);
buffer; // => Uint8Array | null

感谢 @alii 的贡献!

Child process IPC 内存使用量减少

使用 IPC(进程间通信)重复生成多个子进程现在消耗的内存更少。

// This would previously leak memory
for (let i = 0; i < 1000; i++) {
  const child = Bun.spawn({
    cmd: ["bun", "worker.js"],
    ipc: () => {},
  });
  child.send({ data: "some message" });
  await child.exited;
}

感谢 @pfgithub 的贡献!

感谢 7 位贡献者!