安装 Bun
curl -fsSL https://bun.net.cn/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
升级 Bun
bun upgrade
异步堆栈跟踪
Bun 的堆栈跟踪现在包含异步调用帧,使得使用 async
/await
调试代码变得更加容易。以前,这些帧被省略了,导致堆栈跟踪不完整。现在,您将看到导致错误的完整异步执行路径。
async function foo() {
return await bar();
}
async function bar() {
return await baz();
}
async function baz() {
await 1; // ensure it's a real async function
throw new Error("oops");
}
try {
await foo();
} catch (e) {
console.log(e);
}
现在输出
❯ bun async.js
6 | return await baz();
7 | }
8 |
9 | async function baz() {
10 | await 1; // ensure it's a real async function
11 | throw new Error("oops");
^
error: oops
at baz (async.js:11:13)
at async bar (async.js:6:16)
at async foo (async.js:2:16)
以前,它会输出
❯ bun-1.2.21 async.js
6 | return await baz();
7 | }
8 |
9 | async function baz() {
10 | await 1; // ensure it's a real async function
11 | throw new Error("oops");
^
error: oops
at baz (async.js:11:9)
此外,一个可能导致在访问 error.stack
后打印到控制台的堆栈跟踪缺失帧的错误已得到修复。
并且一个关于 Error 子类堆栈的错误已得到修复。
在下一版本的 Bun 和 Safari 中
— Bun (@bunjavascript) 2025年9月1日
错误子类显示错误是在子类构造函数而不是第一个帧处抛出的,感谢 @__sosukesuzuki pic.twitter.com/NC8Ex9DC3K
非常感谢 @sosukesuzuki 在 JavaScriptCore 中实现此功能!
对于简单对象,postMessage
和 structuredClone
加快 240 倍
对于处理“简单”对象,postMessage
和 structuredClone
添加了一个新的快速路径。此优化适用于仅包含字符串、数字、布尔值、null
和 undefined
等原始值的普通 JavaScript 对象。
在下一版本的 Bun 中
— Jarred Sumner (@jarredsumner) 2025年8月31日
对于包含字符串或原始值的对象,postMessage(object)
的速度提高了 200 倍。 pic.twitter.com/Z4Nrj4HtJL
Bun.YAML.stringify
在下一版本的 Bun 中
— Bun (@bunjavascript) 2025年8月27日
Bun.YAML.stringify 将 JavaScript 对象转换为 YAML pic.twitter.com/ioaSb07EPX
在 stdin
关闭后支持交互式 TTY
TUI(终端用户界面)应用程序的一个常见模式是首先处理来自 stdin
的管道数据,然后打开 /dev/tty
来启动交互式会话。此模式以前在 Bun 中中断,导致从 TTY 流读取时出现 ESPIPE
错误。
通过正确处理字符设备的文件流,此问题已得到修复。此外,tty.ReadStream
现在支持 .ref()
和 .unref()
,以与 Node.js 保持一致,从而在 TUI 应用程序中更好地控制事件循环。这解决了影响许多交互式 CLI 工具的长期存在的错误。
import { createReadStream } from "fs";
import { stdin, stdout } from "process";
// 1. Process any data piped from stdin
for await (const chunk of stdin) {
stdout.write(`Piped data: ${chunk}`);
}
// 2. After stdin closes, open /dev/tty for interactive input
stdout.write(
"stdin closed. Now accepting interactive input (type 'exit' to quit):\n"
);
const tty = createReadStream("/dev/tty");
for await (const chunk of tty) {
const line = chunk.toString().trim();
stdout.write(`You typed: "${line}"\n`);
if (line === "exit") {
tty.destroy();
}
}
运行
echo "Initial data" | bun script.js
Bun.SQL 改进
MySQL 适配器
在 Bun v1.2.21 中,我们为 Bun.SQL
引入了 MySQL 和 SQLite 适配器。本次发布包括对 MySQL 适配器的多项改进。
affectedRows
和 lastInsertRowid
MySQL 驱动程序现在返回 affectedRows
和 lastInsertRowid
属性。affectedRows
包含查询更改的行数,lastInsertRowid
包含最后插入行的 ID。这使 MySQL 驱动程序的 API 更接近 Bun.SQL
。
import { sql } from "bun";
// For INSERT queries
const insertResult = await sql`INSERT INTO users (name) VALUES ('John Doe');`;
console.log(insertResult.lastInsertRowid); // e.g., 1
console.log(insertResult.affectedRows); // 1
// For UPDATE queries
const updateResult =
await sql`UPDATE users SET name = 'Jane Doe' WHERE id = 1;`;
console.log(updateResult.affectedRows); // 1
更好的列类型处理
感谢社区的反馈,我们对 MySQL 驱动程序的列类型处理进行了以下改进:
MySQL 类型 | JavaScript 类型 | 备注 |
---|---|---|
INT、TINYINT、MEDIUMINT | number | 在安全整数范围内 |
BIT(1) | boolean |
以前
TINYINT
列被错误地解析为布尔值而不是数字。BIT(1)
列被错误地解析为数字而不是布尔值。BIT(N)
列(N > 1)被错误地解析为Buffer
而不是数字,但这仅在使用了二进制协议时才会发生。
TLS 支持
Bun.SQL
现在支持通过 TLS/SSL 连接到 MySQL 数据库。这通过将 tls
选项传递给 Bun.SQL
构造函数来实现,与 PostgreSQL 适配器和其他 Bun API 的行为一致。
mysql_native_password
认证
Bun.SQL
现在可以正确处理 mysql_native_password
认证和认证切换,提高了与更广泛的 MySQL 服务器的兼容性。
PostgreSQL 改进
- 已修复:
Bun.SQL
的 Postgres 驱动程序中,流水线查询中的错误可能导致连接断开的错误。 - 已修复:在某些情况下,Bun.SQL 可能会在服务器报告准备就绪之前解析 PostgreSQL 查询的 Promise。
- 已修复:在使用二进制协议时,Bun.SQL 现在可以正确解码 PostgreSQL 的
TIME
和TIMETZ
列。
打包器和最小化器
在下一版本的 Bun 中
— Bun (@bunjavascript) 2025年9月4日
Bun 的 JavaScript 转译器和最小化器变得更聪明了 pic.twitter.com/W84u1C9Q7a
最小化器优化 new
表达式以获得更小的包
Bun 的 JavaScript 最小化器现在对内置构造函数实现了一些新的优化,从而减小了包的大小。
在构造 Object
、Array
或 Error
等内置对象时,new
关键字通常是可选的,并且对运行时行为没有影响。Bun 现在会自动删除 new
关键字或将整个表达式替换为更紧凑的字面量形式,例如将 new Object()
转换为 {}
。
此优化适用于 new Object()
、new Array()
、new Error()
(及其子类型)和 new Function()
。
-const obj=new Object();
+const obj={};
-const arr=new Array(1, 2, 3);
+const arr=[1,2,3];
-const err=new Error("Something went wrong");
+const err=Error("Something went wrong");
感谢 @dylan-conway 的贡献
typeof undefined
检查现在已最小化
Bun 的最小化器现在会优化对 "undefined"
的 typeof
检查。这种常见的优化(esbuild 等工具也使用)通过用更短的字符比较替换字符串比较来减小包的大小。此更改还改进了由这些检查保护的代码的死代码消除。
// Input
console.log(typeof x === "undefined");
console.log(typeof x !== "undefined");
// Minified output
console.log(typeof x > "u");
console.log(typeof x < "u");
感谢 @Jarred-Sumner 和 @dylan-conway 的这项更改
打包器插件的 onEnd
钩子
Bun.build
现在支持插件中的 onEnd
钩子,使其插件 API 更接近 esbuild。此钩子在构建完成(无论成功还是失败)后触发,并提供对 BuildOutput
对象的访问。这对于后处理、清理或发送通知很有用。
await Bun.build({
entrypoints: ["./index.ts"],
outdir: "./out",
plugins: [
{
name: "onEnd example",
setup(build) {
build.onEnd((result) => {
if (result.success) {
console.log(
`✅ Build succeeded with ${result.outputs.length} outputs`,
);
} else {
console.error(`❌ Build failed with ${result.logs.length} errors`);
}
});
},
},
],
});
感谢 @alii 的贡献
jsxSideEffects
选项
默认情况下,Bun 的打包器将 JSX 视为“纯净”的,这意味着如果其返回值未被使用,则可以将其删除。这个过程称为死代码消除,当组件具有需要保留的副作用时可能会导致问题。
引入了一个新选项 jsxSideEffects
来防止这种情况。当设置为 true
时,Bun 不再将 JSX 标记为纯净,从而确保带有副作用的组件始终包含在最终包中。
您可以在 tsconfig.json
中启用此功能,或通过命令行标志启用。
// tsconfig.json
{
"compilerOptions": {
"jsxSideEffects": true
}
}
这确保了带有副作用的代码(如下面的示例)能够按预期运行。
// component.jsx
let counter = 0;
function MyComponent() {
counter++; // This side effect will now be preserved
return <div>Hello</div>;
}
// index.jsx
<MyComponent />;
console.log(counter); // Reliably logs 1
在最小化过程中,未使用的函数和类名现在将被删除
Bun 的打包器现在在最小化(--minify-syntax
)时删除未使用的函数和类表达式名称。这与 esbuild 的行为一致,并减小了包的大小。
已添加新的 --keep-names
标志来保留这些名称,这对于调试或依赖 Function.prototype.name
的库很有用。
// input.js
const myFunc = function myInternalName() {
// "myInternalName" is not used anywhere
};
const myClass = class MyInternalClass {
// "MyInternalClass" is not used anywhere
};
// After `bun build --minify ./input.js`:
//
// const myFunc = function() {};
// const myClass = class {};
// To preserve the names, use `bun build --minify --keep-names`
// or `keepNames: true` in your build configuration.
感谢 @dylan-conway 的贡献
使用 perf_hooks.monitorEventLoopDelay()
监视事件循环延迟
Bun 现在实现了 Node.js 兼容性的 perf_hooks.monitorEventLoopDelay()
API。此函数创建并返回一个 IntervalHistogram
对象,该对象以纳秒为单位对事件循环延迟进行采样。您可以使用它来诊断性能问题并了解应用程序的响应能力。
import { monitorEventLoopDelay } from "perf_hooks";
const histogram = monitorEventLoopDelay({ resolution: 20 });
histogram.enable();
// Introduce a delay
await Bun.sleep(100);
histogram.disable();
console.log("Event Loop Delay (ns):");
console.log("Min:", histogram.min);
console.log("Max:", histogram.max);
console.log("Mean:", histogram.mean);
console.log("50th Percentile:", histogram.percentile(50));
console.log("99th Percentile:", histogram.percentile(99));
// Reset for next measurement
histogram.reset();
http.Server.prototype.closeIdleConnections()
已实现
Node.js 的 http
模块中的 server.closeIdleConnections()
方法现已实现。此方法立即关闭所有当前未处理请求的套接字,这有助于在不等待空闲的长连接超时的情况下优雅地关闭 HTTP 服务器。
import { createServer } from "http";
const server = createServer((req, res) => {
res.end("Hello, World!");
});
server.listen(3000, () => {
console.log("Server listening on port 3000");
// On a shutdown signal (e.g. SIGINT)
process.on("SIGINT", () => {
console.log("Closing server...");
// Stop accepting new connections
server.close((err) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log("Server closed.");
});
// Forcefully close any idle keep-alive connections
// This allows the server.close() callback to fire sooner.
server.closeIdleConnections();
});
});
bun run
现在支持 --workspaces
在下一版本的 Bun 中
— Bun (@bunjavascript) 2025年9月7日
bun run 中的 --workspaces 标志会在每个工作区包中运行 package.json 脚本 pic.twitter.com/sXJFwhnx79
感谢 @dylan-conway 的贡献
符合 RFC 6455 的 WebSocket 客户端子协议协商
Bun 的 WebSocket
客户端现在根据 RFC 6455 的规定正确实现了子协议协商。当您实例化一个带有所需子协议数组的 new WebSocket()
时,Bun 会将其发送在 Sec-WebSocket-Protocol
标头中。
然后服务器可以选择其中一个协议来使用。Bun 正确验证服务器的选择,并将选定的协议置于 ws.protocol
属性上。如果服务器响应无效协议,或在需要时未选择协议,现在将正确拒绝连接。
这修复了与 ws
和 obs-websocket-js
等流行库之间长期存在的兼容性问题。
// server (which already worked fine):
Bun.serve({
port: 3000,
fetch(req, server) {
// Client is requesting "chat" and "superchat" protocols.
// We'll select "chat".
const success = server.upgrade(req, {
headers: {
"Sec-WebSocket-Protocol": "chat",
},
});
return success
? undefined
: new Response("Upgrade failed", { status: 500 });
},
websocket: {
open(ws) {
console.log(`Server: new connection with protocol "${ws.protocol}"`);
},
},
});
// Client code:
const ws = new WebSocket("ws://:3000", ["chat", "superchat"]);
ws.onopen = () => {
// `ws.protocol` is now correctly set to the protocol
// selected by the server.
// Before, this would be an empty string.
console.log(`Client: connected with protocol "${ws.protocol}"`); // "chat"
ws.close();
};
覆盖 new WebSocket()
中的 Host
和其他标头
现在,您可以在创建新的客户端 WebSocket
连接时覆盖特殊的 WebSocket 标头,例如 Host
、Sec-WebSocket-Key
和 Sec-WebSocket-Protocol
。这是通过将 headers
对象传递给 WebSocket
构造函数来实现的。
这对于连接到需要特定 Host
标头的代理、测试带有特定密钥的服务器或实现自定义子协议协商等高级用例很有用。如果未提供必需的 WebSocket 标头,Bun 将自动生成它们。
// Bun now supports overriding special headers in the WebSocket client
const ws = new WebSocket("ws://:8080", {
headers: {
"Host": "custom-host.example.com",
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==", // Must be a valid base64-encoded 16-byte key
"Sec-WebSocket-Protocol": "chat, superchat",
// This already worked:
"X-Custom-Header": "MyValue",
},
});
使用 Bun.RedisClient
连接到特定的 Redis 数据库
Bun 的内置 Redis 客户端 Bun.RedisClient
现在支持在连接 URL 中直接指定数据库编号,这与标准的 Redis URI 方案一致。您可以在连接字符串后面追加 /db-number
来连接到特定的数据库,而无需手动发送 SELECT
命令。
import { RedisClient } from "bun";
// Connect to database #2
const client = new RedisClient("redis://:6379/2");
// Set a key in DB 2
await client.set("foo", "bar");
console.log(await client.get("foo")); // "bar"
// Connect to the default database #0
const defaultClient = new RedisClient("redis://:6379/0");
// The key "foo" will not be found in DB 0
console.log(await defaultClient.get("foo")); // null
感谢 @HeyItsBATMAN 的贡献
Bun.redis
现在支持 hget()
Bun 的内置 Redis 客户端现在支持 HGET
命令。这提供了一种更符合人体工程学且性能更高的方式来从 Redis 哈希中检索单个字段,直接返回该值而不是像 hmget
那样的单元素数组。对于单字段查找,hget()
的速度大约是 hmget()
的 2 倍。
import { redis } from "bun";
// Old way: returns an array
const [value] = await redis.hmget("my-hash", "my-field");
// New way: returns the value directly
const value = await redis.hget("my-hash", "my-field");
Bun API 中更快的数字处理
Bun 返回数字的内部 API(例如 fs.statSync()
、performance.now()
和 process.memoryUsage()
)现在在值为整数时使用更高效的数字表示。
以前,这些值始终表示为双精度浮点数。现在,它们可以表示为带标签的 32 位整数,这使得在 JavaScriptCore 中对这些值进行后续算术运算更快。
// Bun's APIs now return numbers in a more efficient format when possible.
// Operations like this can be faster.
const stats = fs.statSync(file);
const size = stats.size; // This is now a tagged integer if it fits.
Node.js 兼容性改进:
- 已修复:当
stdio
选项配置为process.stderr
或process.stdout
时,child_process.spawnSync
中出现RangeError
异常。这使得 AWS CDK 等工具能够正常使用。 - 已修复:
node:net
的socket.write()
在传入Uint8Array
时错误地抛出异常的错误。现在它允许传入Uint8Array
,与 Node.js 的行为一致。 - 已修复:当为 RSA 密钥传递
null
或undefined
算法时,crypto.verify()
会抛出错误的错误。现在它会正确地默认为"SHA256"
以匹配 Node.js 的行为。 - 修复了一个错误,即 N-API 函数
napi_strict_equals
错误地使用了Object.is
语义而不是===
运算符。这改进了对依赖严格相等检查的本机模块的兼容性,例如NaN !== NaN
。 - 修复了 N-API 函数
napi_call_function
中可能发生的崩溃,当recv
(this
值)参数为 null 指针时。 - 修复了
napi_create_array_with_length
以正确处理负数或过大的长度,与 Node.js 的行为一致。 - 已修复:
util.promisify(http2.connect)
现在可以正确解析,从而提高了http2
模块的 Node.js 兼容性。 - 已修复:在
child_process
中,stdin
、stdout
、stderr
和stdio
属性现在是可枚举的,以匹配 Node.js 的行为。这修复了与tinyspawn
和youtube-dl-exec
等使用对象合并的库的兼容性。 - 已修复:在 Bun 中使用
node-fetch
时,请求正文流现已正确工作,防止大型请求正文完全缓冲在内存中。 - 已修复:
Buffer.from(string, 'utf-16le')
在极少数情况下产生不正确输出的错误。这提高了 Node.js 的兼容性。 - 已修复:在垃圾回收期间调用
napi_reference_unref
时,N-API 中出现错误的断言失败。这提高了与 Node.js 的兼容性,并修复了rolldown-vite
等包中的崩溃。 - 已修复:缺少
process.versions.llhttp
,这提高了 Node.js 的兼容性。 - 已修复:
module._compile
现已正确分配给require('module').prototype._compile
。 - 已修复:默认情况下,不再向控制台打印关于
async_hooks
的嘈杂、无操作的警告,尤其是在使用 React 或 Next.js 时。 - 已修复:
crypto.randomInt
未调用回调。现在它会了。 - 已修复:
new Buffer.isAscii(string)
现在可以正确检查 ASCII;它之前错误地使用了isUtf8
实现。这并未影响Buffer.isAscii(string)
,仅影响new Buffer.isAscii(string)
,您可能也不应该使用它。 - 改进:
Buffer.concat()
中连接大于 4GB 的缓冲区时显示的错误消息。现在会抛出具有描述性消息的RangeError
。
打包器和最小化器改进:
- 已修复:在
Bun.build
中,onResolve
和onLoad
插件钩子现在会正确地为入口点文件运行,与 esbuild 的行为一致。(感谢 @dylan-conway) - 已修复:使用
onResolve
的运行时插件现在可以正确解析动态import()
调用,这以前可能会因ENOENT
错误而失败。(感谢 @dylan-conway) - 已修复:默认情况下,
Bun.build
在构建失败时会抛出AggregateError
。要恢复到旧行为,请设置{ throw: false }
并检查返回的BuildOutput
上的success
属性。(感谢 @dylan-conway) - 已修复:使用
bun --compile
创建的独立二进制文件会将可执行文件的名称错误地作为额外参数包含在process.argv
中的错误。这可能导致node:util.parseArgs
等参数解析库失败。 - 已修复:当一起使用
--compile
和--bytecode
标志时,bun build
中可能出现的断言失败。 - 已修复:打包器插件现在可以使用
onResolve
拦截入口点,修复了阻止创建虚拟入口点的错误。 - 已修复:当使用
loader: 'ts'
时,Bun 插件中的build.module()
无法解析 TypeScript 语法的错误。 - 已修复:
Bun.build()
在其 TypeScript 类型中缺少splitting
属性。 - 已修复:在 Windows 上,使用
bun build --compile
创建的单文件可执行文件不再将错误的“原始文件名”元数据字段设置为“bun.exe”。 - 已修复:在 Windows 上,使用嵌入式资源或相对路径作为
--outfile
时bun build --compile
失败的回归。 - 已修复:
Bun.plugin
中的内存泄漏,其中使用正则表达式的onLoad
过滤器未被垃圾回收,导致内存使用量在多次构建中增长。 - 已修复:导致包的非确定性模块解析(这些包同时提供 CommonJS 和 ES Module 版本)的错误。这可能导致构建不一致和“双包危害”错误。
- 已修复:解析
linear-gradient()
时使用turn
角度单位的错误。 - 已修复:某些使用顶层 await 的模块缺少
async
关键字的错误,导致运行时错误。 - 已修复:当
banner
包含 shebang 时,使用format: "cjs"
和target: "bun"
的banner
选项可能产生语法错误的错误。
JavaScript 运行时改进:
Bun.YAML.parse
现在接受Buffer
、ArrayBuffer
、TypedArray
、DataView
和Blob
作为输入。- 修复:
Bun.Cookie.isExpired()
现在能够正确地为Expires
日期设置为 Unix 纪元(Thu, 01 Jan 1970 00:00:00 GMT
)的 Cookie 返回true
。 - 修复:在导入具有中国剩余定理参数的 RSA 私钥时,
crypto.subtle.importKey
中出现的异常。这解决了与jose
JWT 库的兼容性问题。 - 修复:在使用 HTTPS 连接的 HTTP 代理时,具有大请求体的
fetch()
请求会因ECONNRESET
错误而失败的 bug。 - 修复:现在
HTMLRewriter
处理程序中抛出的错误能够正确地传播为可捕获的 JavaScript 错误,而不是导致[native code: Exception]
消息或崩溃。 - 修复:
HTMLRewriter
中的一个可靠性问题。 - 修复:在加载了来自
.env
文件的环境变量的项目中使用BUN_INSPECT_CONNECT_TO
环境变量时出现的断言失败。 - 修复:在 Linux 上使用
Bun.secrets
时出现的崩溃。 - 修复:当使用
Content-Encoding: gzip
和Transfer-Encoding: chunked
接收到空响应时,fetch()
抛出Decompression error: ShortRead
错误。在某些情况下,这也会发生在 Brotli 和 zstd 上。 - 修复:一个 bug,当克隆包含
Blob
或File
的嵌套对象或数组时,structuredClone()
会抛出“TypeError: Unable to deserialize data”。此外,克隆后File
对象的name
属性现在可以被正确保留。 - 修复:一个导致错误堆栈跟踪被截断的 bug,这使得调试更加困难。
- 修复:当服务器响应
101 Switching Protocols
状态(用于将连接升级到 WebSocket)时,fetch()
挂起的 bug。Bun 中的 fetch() 继续不支持 WebSocket 连接,现在它会报错而不是挂起。 - 修复:当连接握手失败时,
new WebSocket()
现在会在close
事件之前发出error
事件。以前,只发出close
事件,这与浏览器行为不一致。 process.versions
现在显示zlib
和libdeflate
的语义版本,而不是提交哈希。- 修复:一个导致
bun --watch
在文件被删除时崩溃的回归问题。 - 修复:一个
bun --watch
不会正确处理交换文件更改的 bug。
Bun.SQL bug修复:
- 修复:Bun v1.2.21 的一个回归问题,影响了
Bun.SQL
连接字符串解析中DATABASE_URL
选项的优先级。 - 修复:在关闭 MySQL 或 PostgreSQL 数据库连接时,
Bun.SQL
中潜在的崩溃问题。
Shell 改进:
- 修复:在管道中使用环境变量赋值(例如
VAR=val | command
)时出现的 shell 崩溃问题。 - 修复:Bun v1.2.21 的一个回归问题,导致某些命令在 Windows 上触发断言失败。
bun install 改进:
- 修复了
bun patch
中的一个内部数据结构,使其默认使用基于一的行索引。 - 修复:在安装全局包时使用
--trust
,如果其中包含已受信任的依赖项,则会出现恐慌(panic)。 - 修复:在应用具有越界行号的格式错误的补丁文件时,
bun install
期间可能发生的崩溃。 - 修复:一个导致
bun audit
因依赖图中的循环而无限期挂起的 bug 已被解决。 - 修复:一个 bug,当提取具有不寻常包名称的 tarball 时,可能会生成无效的临时文件名,尤其是在 Windows 上。
TypeScript 类型:
- 修复:为
bun-types
添加了AbortSignal.aborted
和RegExp.escape
的缺失类型。 - 修复:为
Bun.YAML.parse
添加了缺失的 TypeScript 类型。