如果你用 Bun 做服务端、CLI 或者构建工具,大概率已经习惯了它每隔几周就「塞一堆能力进运行时」的节奏。Bun v1.3.14(2026-05-13 发布)这次的版本仍然是这种风格,但密度比平时更高一些:
sharpfetch() 自己长出了 HTTP/2 与 HTTP/3 客户端下面按「你为什么应该关心」的顺序,把这次发布拆开讲。
Bun 1.3.14 的更新可以归到三条主线:
Bun.Image)、HTTP/3 服务、fetch 的 HTTP/2/3 客户端、Windows 上的 Bun.Terminal——都是「原本需要装库才能做」的事,现在变成了运行时自带。install.globalStore,让 --linker=isolated 在大型 Monorepo 下的速度,从「比 hoisted 慢一点」直接变成「快一个数量级」。fs.watch() 后端重写、JavaScriptCore 升级、跨语言 LTO、ESM 加载更快、二进制体积变小、内存占用下降。外加几个偏「细节地狱」但很值钱的修复:FormData 多部分边界格式(影响 OpenAI API)、ECH GREASE 导致的 fetch 卡死、MySQL BLOB 在 GC 时被破坏,等等。
Bun.Image:把 sharp 的 80% 写进运行时这一项是这次发布里覆盖面最广、感知最直接的能力。
Bun 1.3.14 新增了 Bun.Image —— 一个链式调用的图像处理 API。能力范围:
ArrayBuffer / TypedArray、Blob / BunFile / S3File、data: URLbytes() / buffer() / blob() / toBase64() / dataurl() / placeholder()(thumbhash)/ metadata() / write()metadata() 外都在主线程之外执行官方示例:
await Bun.file("photo.jpg")
.image()
.resize(1024, 1024, { fit: "inside" })
.rotate(90)
.webp({ quality: 85 })
.write("thumb.webp");性能对比(vs sharp 0.34.5):
metadata():~70× 更快我的评价是:sharp 仍然是 Node 生态的事实标准,但对「只需要做缩略图 / 格式转换 / 提取元数据」的常见场景来说,Bun.Image 已经能完全替代。最大的现实收益不是性能,而是——
少一个 node-gyp / 原生模块构建链路。
任何在 Docker / 边缘运行时部署过 sharp 的人都会理解这句话的价值。
bun install --linker=isolated 是 Bun 的「pnpm 风格」装包模式(每个包独立 node_modules、靠符号链接组合)。它的卖点是安全(防幽灵依赖)和磁盘节省,但代价一直是——比 hoisted 模式慢一点。
1.3.14 引入了 install.globalStore 选项,把所有项目共享一个全局虚拟存储池。
基准(Apple Silicon、1400 个包的 fixture):
| Linker 模式 | 耗时 |
|---|---|
| Hoisted | 823ms |
| Isolated(旧) | 841ms |
| Isolated + globalStore | 115ms |
clonefileat 系统调用次数:0。
启用方式(bunfig.toml):
[install]
globalStore = true或者用环境变量:
BUN_INSTALL_GLOBAL_STORE=1 bun install为什么这件事重要:
node_modules 节省如果你之前因为「太慢」而没用 isolated linker,这次值得重新评估。
Bun.serve 现在可以直接吐 HTTP/3,由 lsquic v4.6.2 驱动。
Bun.serve({
port: 443,
tls: { cert, key },
http3: true,
fetch(req) { return new Response("hi"); },
});官方给出的吞吐数据(Linux x64):
| 场景 | HTTPS/1.1 | HTTP/3 |
|---|---|---|
| 静态路由 | 189,130 req/s | 509,135 req/s |
| 动态 fetch handler | 142,323 req/s | 283,485 req/s |
但目前还有不少限制,官方明确标注「highly experimental」:
Expect: 100-continue我的判断:
fetch() 的 HTTP/2 与 HTTP/3 客户端(实验性)这是这次发布里我个人最期待的能力之一。
Bun 内置 fetch() 一直只跑 HTTP/1.1。1.3.14 同时上了两个实验性客户端:
开启方式:
# 全局开关
BUN_FEATURE_FLAG_EXPERIMENTAL_HTTP2_CLIENT=1 bun run app.ts
# 或 CLI flag
bun --experimental-http2-fetch app.ts或者按请求开启:
const res = await fetch("https://example.com", { protocol: "http2" });能力清单:
REFUSED_STREAM / GOAWAY 自动重试Content-Length 严格校验(RFC 9113 §8.1.1)Expect: 100-continue不支持:HTTP 代理 / CONNECT、Unix sockets、server push、明文 HTTP/2(h2c)。
const res = await fetch("https://example.com/", { protocol: "http3" });支持所有 HTTP 方法、重定向、gzip、ReadableStream 上传、全双工流、AbortSignal,以及 Alt-Svc 协商的 HTTP/3 升级(RFC 7838,需要 --experimental-http3-fetch)。
为什么这件事值得关注:
之前在 Bun 里要发 HTTP/2 请求,要么用 Node 兼容层的
node:http2,要么外挂一个 client。现在「fetch()直接说话」,对调用云厂商 API、对接 gRPC-Web、跨区域回源等场景,是真实的减负。
fs.watch() 完全重写:Linux / macOS / FreeBSDfs.watch() 是 Node 生态老大难。Bun 这次直接对接 OS 原生 API:
伴随的修复:
如果你之前在 dev server、热重载、chokidar 这条链上踩过「watcher 偶尔不触发」的坑,这次升级就是答案。
bun --no-orphans:进程死了,孩子也别活着一个看起来很小、但实际很解气的 flag:
bun --no-orphans run my-script行为:父进程一旦死亡,递归 SIGKILL 所有后代进程。
实现上:
prctl(PR_SET_PDEATHSIG, SIGKILL)kqueue 的 EVFILT_PROC / NOTE_EXIT适用场景非常具体但很高频:
以前要靠 tini / dumb-init / 自己写 trap,现在加一个 flag 就行。
Bun.Terminal(ConPTY)Bun.Terminal 之前只在 macOS / Linux 上能用。1.3.14 通过 CreatePseudoConsole(ConPTY)补齐了 Windows 支持。
平台差异需要注意:
但对跨平台 CLI 工具来说,「能在三个平台跑同一份代码」本身就是巨大的简化。
using / await usingBun 不再把 using / await using 声明转译成辅助函数调用——前提是 target 是 Bun:
bun runBun.Transpiler({ target: "bun" })bun build --target=bun这意味着资源管理(文件句柄、连接、锁)可以用规范语法写,且没有运行时开销。
{
using db = openDatabase();
// ...
} // db 自动关闭process.execve():与 Node 24 对齐process.execve("/usr/bin/echo", ["echo", "hello"], { PATH: process.env.PATH });注意:在 Worker 线程和 Windows 上会抛错。
node:http 中 NodeHTTPResponse 缓冲未释放的内存泄漏res.setTimeout() 保活 event loophttps.request() 忽略 checkServerIdentity 回调node:zlib 的 onerror 回调 use-after-freecrypto.scrypt 分配失败时的内存泄漏crypto.randomFill 越界堆溢出Buffer.copyBytesFrom() 在 byteOffset 非零时的行为node:http2 在重入 JS 回调时的 use-after-freeBun.spawn 的 stdin 管道泄漏Bun.serve() 在 ReadableStream / FormData 路径下的内存泄漏Bun.RedisClient 在重连失败后卡死Bun.FileSystemRouter 的崩溃与内存泄漏TextDecoder UTF-16 内存泄漏Blob / File 显示 [detached] 的问题WebSocket.close() 在 CONNECTING 阶段时 socket 卡住TransformStream 的 GC root 环导致 OOM如果你之前在 OpenAI / Anthropic API 调用上偶尔遇到莫名其妙的 400 或卡死,这次升级值得专门提一下。
这部分对「不升级也不会出错,但升级了就能直接受益」的同学:
Array.prototype.shift fastShift、短字符串 JSON.parse、单字符 startsWith / endsWith、Intl.NumberFormat 创建)us_* ← Zig 69%,C++ uws_* ← Zig 70%,mi_free 100%
Bun.escapeHTML 快 6.5%、TextDecoder.decode 快 2.6%、HTTP 吞吐快 3.5%--use-system-ca 即可返回系统 CA;macOS 不再因为网络 OCSP/CRL/AIA 拉取而卡 10 秒;Windows 新增加载 CA、TrustedPeople、GROUP_POLICY、ENTERPRISE 存储新增 FreeBSD 与 Android 的第一方原生构建。
升级命令:
# 已安装
bun upgrade
# 全新安装
curl -fsSL https://bun.sh/install | bash我的升级 checklist:
install.globalStore,测一次 isolated linkerBun.Image,看看能不能把原生依赖踢掉fetch() HTTP/2/3 都还是 experimental,先在非关键链路上跑跑数据,再决定要不要打开Bun 1.3.14 不是一次「换个版本号」的发布,它有几个我认为值得记住的方向:
如果你已经在用 Bun,这是个强烈建议升级的版本;如果你还在「Node vs Bun」之间纠结,这次发布把天平又往 Bun 一边推了一点。
Bun.Image 文档:https://bun.com/docs/api/image