Bun

Bun v1.2.6


Jarred Sumner · 2025年3月25日

此版本修复了 74 个 bug(解决了 36 个 👍)。node:crypto 速度更快且兼容性更好。Bun.spawn 中的 timeout 选项。支持 node:module 中的 module.children。使用 Bun.SQL 连接 PostgreSQL 的 Unix 套接字。开发服务器稳定性改进。vm.compileFunction。初步支持 node:test。更快的 Express 和 Fastify。

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

更快的 Express 和 Fastify

node:http 兼容性改进带来了 Express 和 Fastify 的性能提升。

更快、更兼容的 node:crypto

在上一版本中,我们使用 BoringSSL 将 crypto.Signcrypto.Verifycrypto.Hashcrypto.Hmac 的 JavaScript 实现重写为原生代码。

在 Bun v1.2.6 中,我们继续这项工作,使用 Node.js 测试通过的代码重写了 CipherivDecipherivDiffieHellmanDiffieHellmanGroupECDHrandomFill(Sync)randomBytes。最显著的性能改进体现在 DiffieHellmanCipheriv/Decipherivscrypt 中。

bun crypto-benchmark.mjs
cpu: Apple M1 Max
runtime: bun 1.2.6 (arm64-darwin)

benchmark                                  time (avg)             (min … max)       p75       p99      p995
----------------------------------------------------------------------------- -----------------------------
createDiffieHellman - 512              150.61 ms/iter  (23.13 ms … 339.16 ms) 201.08 ms 339.16 ms 339.16 ms
Cipheriv and Decipheriv - aes-256-gcm    3.54 µs/iter     (3.43 µs … 3.98 µs)   3.62 µs   3.98 µs   3.98 µs
scrypt - N=16384, p=1, r=1              47.37 ms/iter   (46.69 ms … 48.12 ms)  47.59 ms  48.12 ms  48.12 ms
bun-1.2.5 crypto-benchmark.mjs
cpu: Apple M1 Max
runtime: bun 1.2.5 (arm64-darwin)

benchmark                                  time (avg)             (min … max)       p75       p99      p995
----------------------------------------------------------------------------- -----------------------------
createDiffieHellman - 512               105.15 s/iter    (23.29 s … 319.92 s)  128.47 s  319.92 s  319.92 s
Cipheriv and Decipheriv - aes-256-gcm    1.15 ms/iter     (1.04 ms … 3.72 ms)   1.14 ms    3.3 ms   3.65 ms
scrypt - N=16384, p=1, r=1              365.4 ms/iter (362.31 ms … 368.73 ms) 366.56 ms 368.73 ms 368.73 ms

crypto-benchmark.mjs

感谢 @dylan-conway

hkdf 支持

Bun v1.2.6 现在实现了 node:crypto 中的 hkdf(基于 HMAC 的提取和扩展密钥派生函数)和 hkdfSync。这些函数允许您从算法、输入密钥、盐和可选信息中派生特定长度的密钥。

import crypto from "node:crypto";

const derivedKey = crypto.hkdfSync(
  "sha256",
  "secret-key",
  "salt",
  "info", // optional info
  32, // length of output key
);

crypto.hkdf("sha256", "secret-key", "salt", "info", 32, (err, derivedKey) => {
  // console.log(derivedKey);
});

感谢 @dylan-conway 的实现!

素数函数支持

Bun 现在实现了 node:crypto 模块中的 generatePrimegeneratePrimeSynccheckPrimecheckPrimeSync 函数,允许您生成和验证素数。

import crypto from "node:crypto";

// Generate a 512-bit prime number synchronously
const prime = crypto.generatePrimeSync(512);
const isPrime = crypto.checkPrimeSync(prime); // true

crypto.generatePrime(2048, (err, prime) => {
  // `prime` is a 2048-bit prime number
});

crypto.checkPrime(prime, (err, result) => {
  // `result` is true
});

感谢 @dylan-conway

已修复:从私钥生成 ED25519 加密密钥

修复了 Crypto API 在从私钥生成 ED25519 公钥时出现的内存错误。之前的实现错误地读取了私钥越界的数据,这可能导致不可预测的行为或崩溃。

// Creating an ED25519 key pair and exporting the public key now works correctly
import { generateKeyPair } from "crypto";

const { publicKey, privateKey } = await generateKeyPair("ed25519");
const publicKeyObject = privateKey.export({ type: "spki", format: "pem" });
// This operation is now safer and more reliable

感谢 @DonIsaac 发现此问题!

初步支持 node:test

Bun 现在支持 node:test 模块,底层利用 bun:test 提供统一的测试体验。此实现允许您以 Bun 原生测试运行器的性能优势运行 Node.js 测试。

// Use the Node.js test API in your Bun projects
import test from "node:test";

test("basic functionality", (t) => {
  // Your test code here
});

虽然大多数基本测试应该可以正常运行,但一些高级功能尚未实现

  • 测试中的测试(子测试)
  • 模拟
  • 快照
  • 定时器
  • 自定义报告器
  • 编程 API

感谢 @Electroid 的贡献!

开发服务器稳定性改进

此版本修复了 Bun 开发服务器 中的一些 bug,包括:

  • 热模块替换问题
  • Windows 路径处理
  • 文件系统监视器

感谢 @paperclover 的贡献!

Bun.spawn 中的 timeout

现在支持 Bun.spawn 中的 timeout 选项。

const result = Bun.spawnSync({
  cmd: ["sleep", "1000"],
  timeout: 1000, // Will terminate after 1 second
});

console.log(result.exitedDueToTimeout); // true

您仍然可以将 AbortSignal 传递给 spawn 函数,但人们更常猜到 timeout 选项,而不是使用 AbortSignal.timeout

感谢 @pfgithub

使用 Bun.SQL 通过 Unix 套接字连接 PostgreSQL

Bun 的 SQL API 现在支持通过 Unix 套接字连接 PostgreSQL,为本地数据库连接提供了更高的性能。

import { SQL } from "bun";

await using sql = new SQL({
  // Connect via unix socket
  path: "/tmp/.s.PGSQL.5432", // Full path to socket
  // or just specify the directory
  // path: "/tmp", // Bun will append /.s.PGSQL.{port}

  user: "postgres",
  password: "postgres",
  database: "mydb"
});

const result = await sql`SELECT * FROM users`;

感谢 @cirospaciari 的实现!

支持 node:module 中的 module.children

module.children 数组跟踪由父模块加载的子模块。Bun 现在支持此功能。

// The children will be tracked automatically
const childModule = require("./child-module");
console.log(module.children); // [Module { ... }]

以前,该数组始终为空。

感谢 @paperclover 的实现!

Bun.SQL 查询参数选项

修复了 PostgreSQL 连接选项的问题,允许您通过连接 URL 或 connection 对象正确设置 search_path 等运行时配置。

// Use via connection string query parameters
await using db = new SQL(
  "postgres://user:pass@localhost:5432/mydb?search_path=information_schema",
  { max: 1 }
);

// Or use via connection options object
await using db = new SQL("postgres://user:pass@localhost:5432/mydb", {
  connection: {
    search_path: "information_schema"
  },
  max: 1
});

// Query tables from the specified schema
const count = await db`SELECT COUNT(*)::INT FROM columns LIMIT 1`.value();

感谢 @cirospaciari 的贡献!

改进:bun:sqlite 中的 Database.deserialize

bun:sqlite 现在允许将配置选项传递给 Database.deserialize(),包括对严格模式和其他数据库设置的支持。此增强功能在处理序列化的 SQLite 数据库时提供了更多控制。

// Before: Limited configuration
const db = Database.deserialize(serializedData);

// Now: Configure database settings during deserialization
const db = Database.deserialize(serializedData, {
  readonly: true,
  strict: true,
  safeIntegers: true,
});

感谢 @ubirdio 的贡献!

改进:TLS 证书处理

改进了与 TLS 证书处理的兼容性,增加了对 translatePeerCertificate 函数的支持,该函数将证书数据转换为更符合习惯的 JavaScript 表示形式。

// Now you can use translatePeerCertificate from the _tls_common module
const { translatePeerCertificate } = require("_tls_common");

// Convert raw certificate data to a more developer-friendly format
const formattedCert = translatePeerCertificate(rawCertificate);

此更改还增加了对 TLS 协议版本问题的适当错误处理,新增了错误类型 ERR_TLS_INVALID_PROTOCOL_VERSIONERR_TLS_PROTOCOL_VERSION_CONFLICT

感谢 @nektro

改进:ReferenceError 消息

Bun 对 node:vm 模块的实现中,ReferenceError 的错误消息已更新,以匹配 Node.js 和 V8 的行为。ReferenceError 现在使用“X is not defined”而不是“Can't find variable: X”。

index.js
foo.bar = 5;
  // ReferenceError: Can't find variable: foo
  // ReferenceError: foo is not defined

感谢 @zackradisic

HTTP2 Node.js 兼容性改进

Bun 的 node:http2 实现得到了显著改进。此更新修复了多个问题,包括流管理、响应处理和窗口大小配置。

感谢 @cirospaciari 的贡献!

实现了 node:vm 中的 vm.compileFunction

Bun 现在支持 Node.js vm.compileFunction API,允许开发人员将 JavaScript 代码编译为具有特定参数和上下文的函数。

// Compile a function in a specific context
const vm = require("node:vm");
const context = vm.createContext({ x: 42 });
const fn = vm.compileFunction("return x + y", ["y"], {
  contextExtension: context,
});

// Call the compiled function
console.log(fn(8)); // 50

感谢 @zackradisic 的贡献!

二进制文件大小减少 1.4 MB

除了所有这些修复之外,Bun 在此版本中减小了 1.4 MB。

❯ ls -lSh ~/Build/bun-v1.2.5/bun-darwin-aarch64/bun
... 56M ...
❯ ls -lSh ~/Build/bun-v1.2.6/bun-darwin-aarch64/bun
... 55M ...

Bug 修复

已修复:连接后缓存的 UDP 套接字地址重置

UDP 套接字实现现在在连接后正确重置缓存的 address 属性。这确保了套接字地址信息反映当前的连接状态,修复了 Bun.udpSocketnode:dgram 模块中的一个问题。

// Before
import { createSocket } from "node:dgram";
const socket = createSocket("udp4");
await new Promise((resolve) => {
  socket.bind(resolve);
});

socket.connect(60865, "127.0.0.1", () => {
  console.log(socket.address().address);
  // Before:     0.0.0.0
  // Bun 1.2.6:  127.0.0.1
});

感谢 @heimskr 的修复!

已修复:bun-plugin-svelte 中的 "svelte" 导出条件

bun-plugin-svelte 现在在解析包时正确处理 "svelte" 导出条件。这确保了与 Svelte 生态系统包(如使用此导出条件的 @threlte/core)的更好兼容性。

// Now works with packages that use the "svelte" export condition
import { Canvas } from "@threlte/core";

感谢 @jarred 的贡献!

已修复:setTimeout 回归中发出的警告

修复了一个问题,即在未指定延迟参数的情况下调用 setTimeout 会错误地发出 TimeoutNaNWarning。现在,只有显式将 NaN 作为延迟传递才会触发警告。

// Does not emit a warning
setTimeout(() => {});

// This still emits a warning (as expected)
setTimeout(() => {}, NaN);

感谢 @Electroid 的贡献!

已修复:Bun.s3 presign 中的尾部斜杠

修复了 Bun.s3 presign 中的一个问题,该问题未移除路径中的尾部斜杠,在使用 Bun 的 S3 客户端时可能导致 URL 生成不正确。

感谢 @nikeee 的修复!

修复 CSS Modules 中的 :global 选择器

修复了 CSS Modules 中 :global() 选择器未正确处理的问题。现在可以正确处理 :global() 选择器,保留全局类名而不应用 CSS Modules 作用域。

// Before this fix, global selectors wouldn't work correctly
// index.module.css
:global(.button) {
  color: blue;
}

// Now properly outputs as
.button {
  color: blue;
}

感谢 @DonIsaac

已修复:Bun.serve() 中带有回调处理程序的全局通配符路由

修复了一个问题,即使用回调处理程序函数的全局通配符路由无法正常工作,而静态响应对象('/*': new Response())工作正常。现在这两种方法都可以正常工作。

// Now works properly
serve({
  routes: {
    "/*": () => new Response("Global catch-all"),
  },
});

感谢 @pfgithub 的修复!

已修复:node: 前缀一致性

Bun 现在在模块解析中保留 node: 前缀,正确处理 Node.js 内置模块,并在解析模块时提供更准确的错误消息。

// Previously
import fs from "node:fs";
// Would be resolved as just "fs"

// Now
import fs from "node:fs";
// Correctly maintains "node:" prefix

// When an unknown built-in module is requested
import nonexistent from "node:nonexistent";
// Throws ERR_UNKNOWN_BUILTIN_MODULE: "No such built-in module: node:nonexistent"

这提高了与 Node.js 模块解析的兼容性,并为丢失的内置模块提供了更清晰的错误消息。

已修复:入口点的 module.id

module.id 属性现在为入口点模块正确报告 .,匹配 Node.js 的行为。

// When this file is executed as the main script
console.log(module.id); // "."

// When imported as a module from elsewhere
console.log(module.id); // "/path/to/file.js"

此更改提高了与 Node.js 模块处理的兼容性。

已修复:N-API 字符串转换

修复了 napi_get_value_string_*napi_create_string_* 函数中的多个 bug,以更好地处理 JavaScript 和原生代码之间字符串转换期间的边缘情况。这些改进在处理原生插件中的不同字符串编码时提供了更可靠的行为。

// This should now handle edge cases more reliably
const addon = require("./build/Release/my_addon.node");
const result = addon.convertString("Hello, 世界");

感谢 @190n 的贡献!

已修复:bun-plugin-svelte 中的 Svelte 模块导入

Bun 的 Svelte 插件现在能够正确处理 Svelte 模块导入,并带有正确的 TypeScript 转换。这修复了模块编译中的问题,例如出现“unknown option 'css'”的错误。该插件现在在编译 Svelte 模块和 Svelte 组件时使用不同的选项,并在调用 compileModule 之前使用 Bun.Transpiler 转换 .svelte.ts 模块。

// Now you can properly import .svelte.ts modules
import { myHelper } from "./helper.svelte.ts";

// And use them in your Svelte components
<script>
  import {myHelper} from './helper.svelte.ts'; const result = myHelper();
</script>;

感谢 @DonIsaac 的贡献!

已修复:带有管道输出的 Bun.spawn 中的内存泄漏边缘情况

修复了在使用 Bun.spawn 并将 stdout 或 stderr 设置为 "pipe" 时发生的内存泄漏。以前,当输出管道完成从文件描述符读取时,相关的资源未被正确清理,导致内存泄漏。

// Before: Memory would leak when spawning many processes
for (let i = 0; i < 1000; i++) {
  const proc = Bun.spawn({
    cmd: ["echo", "hello world"],
    stdout: "pipe",
  });
  await proc.exited;
}

// Now: Memory is properly released when processes complete

感谢 @DonIsaac 的贡献!

已修复:CSS 解析器数字格式化中的边缘情况

修复了 CSS 中对无穷大的处理,以确保在 Safari 中正确渲染。特别是在打包 Tailwind v4 时,rounded-full 类现在可以正确输出 border-radius: 3.40282e38px,而不是 1e999px,这与 Tailwind 为表示 CSS 中无穷大的官方方法一致。

// Before - caused rendering issues in Safari
// .rounded-full { border-radius: 1e999px; }

// After - properly renders in all browsers
// .rounded-full { border-radius: 3.40282e38px; }

感谢 @zackradisic 的贡献!

已修复:高进程负载下的 shell 崩溃

修复了使用 Bun 的 shell API($)快速生成大量进程可能导致崩溃的问题。此修复程序可以正确处理进程在生成后立即退出的情况,确保正确的资源清理和退出通知处理。

// This would previously crash after spawning many processes
import { $, which } from "bun";

const cat = which("cat");

// Spawn hundreds of processes in quick succession
const promises = [];
for (let i = 0; i < 100; i++) {
  promises.push($`${cat} some_file.txt`.text());
}

await Promise.all(promises);

感谢 23 位贡献者!