Bun

Bun v1.2.22


Jarred Sumner · 2025年9月14日

安裝 Bun

curl
npm
powershell
scoop
brew
docker
curl
curl -fsSL https://bun.nodejs.com.tw/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

非同步堆疊跟蹤

Bun 的堆疊跟蹤現在包含非同步呼叫幀,使得使用 async/await 除錯程式碼變得更加容易。以前,這些幀被省略了,導致堆疊跟蹤不完整。現在,您將看到導致錯誤的完整非同步執行路徑。

async.js
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 子類堆疊的錯誤已得到修復。

非常感謝 @sosukesuzuki 在 JavaScriptCore 中實現此功能!

對於簡單物件,postMessagestructuredClone 加快 240 倍

對於處理“簡單”物件,postMessagestructuredClone 添加了一個新的快速路徑。此最佳化適用於僅包含字串、數字、布林值、nullundefined 等原始值的普通 JavaScript 物件。

Bun.YAML.stringify

stdin 關閉後支援互動式 TTY

TUI(終端使用者介面)應用程式的一個常見模式是首先處理來自 stdin 的管道資料,然後開啟 /dev/tty 來啟動互動式會話。此模式以前在 Bun 中中斷,導致從 TTY 流讀取時出現 ESPIPE 錯誤。

透過正確處理字元裝置的檔案流,此問題已得到修復。此外,tty.ReadStream 現在支援 .ref().unref(),以與 Node.js 保持一致,從而在 TUI 應用程式中更好地控制事件迴圈。這解決了影響許多互動式 CLI 工具的長期存在的錯誤。

script.js
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 介面卡的多項改進。

affectedRowslastInsertRowid

MySQL 驅動程式現在返回 affectedRowslastInsertRowid 屬性。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、MEDIUMINTnumber在安全整數範圍內
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 的 TIMETIMETZ 列。

打包器和最小化器

最小化器最佳化 new 表示式以獲得更小的包

Bun 的 JavaScript 最小化器現在對內建建構函式實現了一些新的最佳化,從而減小了包的大小。

在構造 ObjectArrayError 等內建物件時,new 關鍵字通常是可選的,並且對執行時行為沒有影響。Bun 現在會自動刪除 new 關鍵字或將整個表示式替換為更緊湊的字面量形式,例如將 new Object() 轉換為 {}

此最佳化適用於 new Object()new Array()new Error()(及其子型別)和 new Function()

javascript
-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

感謝 @dylan-conway 的貢獻

符合 RFC 6455 的 WebSocket 客戶端子協議協商

Bun 的 WebSocket 客戶端現在根據 RFC 6455 的規定正確實現了子協議協商。當您例項化一個帶有所需子協議陣列的 new WebSocket() 時,Bun 會將其傳送在 Sec-WebSocket-Protocol 標頭中。

然後伺服器可以選擇其中一個協議來使用。Bun 正確驗證伺服器的選擇,並將選定的協議置於 ws.protocol 屬性上。如果伺服器響應無效協議,或在需要時未選擇協議,現在將正確拒絕連線。

這修復了與 wsobs-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 標頭,例如 HostSec-WebSocket-KeySec-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.stderrprocess.stdout 時,child_process.spawnSync 中出現 RangeError 異常。這使得 AWS CDK 等工具能夠正常使用。
  • 已修復:node:netsocket.write() 在傳入 Uint8Array 時錯誤地丟擲異常的錯誤。現在它允許傳入 Uint8Array,與 Node.js 的行為一致。
  • 已修復:當為 RSA 金鑰傳遞 nullundefined 演算法時,crypto.verify() 會丟擲錯誤的錯誤。現在它會正確地預設為 "SHA256" 以匹配 Node.js 的行為。
  • 修復了一個錯誤,即 N-API 函式 napi_strict_equals 錯誤地使用了 Object.is 語義而不是 === 運算子。這改進了對依賴嚴格相等檢查的本機模組的相容性,例如 NaN !== NaN
  • 修復了 N-API 函式 napi_call_function 中可能發生的崩潰,當 recvthis 值)引數為 null 指標時。
  • 修復了 napi_create_array_with_length 以正確處理負數或過大的長度,與 Node.js 的行為一致。
  • 已修復:util.promisify(http2.connect) 現在可以正確解析,從而提高了 http2 模組的 Node.js 相容性。
  • 已修復:在 child_process 中,stdinstdoutstderrstdio 屬性現在是可列舉的,以匹配 Node.js 的行為。這修復了與 tinyspawnyoutube-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 中,onResolveonLoad 外掛鉤子現在會正確地為入口點檔案執行,與 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 上,使用嵌入式資源或相對路徑作為 --outfilebun build --compile 失敗的迴歸。
  • 已修復:Bun.plugin 中的記憶體洩漏,其中使用正則表示式的 onLoad 過濾器未被垃圾回收,導致記憶體使用量在多次構建中增長。
  • 已修復:導致包的非確定性模組解析(這些包同時提供 CommonJS 和 ES Module 版本)的錯誤。這可能導致構建不一致和“雙包危害”錯誤。
  • 已修復:解析 linear-gradient() 時使用 turn 角度單位的錯誤。
  • 已修復:某些使用頂層 await 的模組缺少 async 關鍵字的錯誤,導致執行時錯誤。
  • 已修復:當 banner 包含 shebang 時,使用 format: "cjs"target: "bun"banner 選項可能產生語法錯誤的錯誤。

JavaScript 執行時改進:

  • Bun.YAML.parse 現在接受 BufferArrayBufferTypedArrayDataViewBlob 作為輸入。
  • 修復: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: gzipTransfer-Encoding: chunked 接收到空響應時,fetch() 丟擲 Decompression error: ShortRead 錯誤。在某些情況下,這也會發生在 Brotli 和 zstd 上。
  • 修復:一個 bug,當克隆包含 BlobFile 的巢狀物件或陣列時,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 現在顯示 zliblibdeflate 的語義版本,而不是提交雜湊。
  • 修復:一個導致 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.abortedRegExp.escape 的缺失型別。
  • 修復:為 Bun.YAML.parse 添加了缺失的 TypeScript 型別。

感謝 14 位貢獻者!