Bun
    Bun

Bun v1.1.27


Chloe Caruso · 2024 年 9 月 7 日

Bun v1.1.27 版本發布了!此版本修正了 130 個錯誤(解決了 250 個 👍 的問題)。bun pm pack、更快的 node:zlib。Bun.serve() 中的靜態路由。response.clone() & request.clone() 中支援 ReadableStream。每個請求的逾時。呼叫了 ReadableStream 中的 Cancel 方法。bun run 更好地處理 CTRL + C。更快的緩衝串流。bun outdated 套件過濾。在 --hot 和 --watch 中監看任意檔案類型。修正了 Windows 上 Proxy 的問題。多項 Node.js 相容性改進。

我們正在舊金山招聘系統工程師,共同打造 JavaScript 的未來!

安裝 Bun

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

原生 node:zlib

我們重寫了 node:zlib 以使用原生程式碼。

執行階段node:zlib串流 (MB/s)同步 (MB/s)
Bun v1.1.27deflate32.79 MB/s14.82 MB/s
Node v22.5.1deflate15.50 MB/s31.39 MB/s
Bun v1.1.26deflate15.59 MB/s10.29 MB/s
Bun v1.1.27deflateRaw32.68 MB/s14.60 MB/s
Node v22.5.1deflateRaw19.77 MB/s31.41 MB/s
Bun v1.1.26deflateRaw15.67 MB/s10.38 MB/s
Bun v1.1.27gunzip87.72 MB/s107.60 MB/s
Bun v1.1.26gunzip46.49 MB/s42.74 MB/s
Node v22.5.1gunzip31.01 MB/s75.86 MB/s
Bun v1.1.27gzip32.69 MB/s14.91 MB/s
Node v22.5.1gzip18.46 MB/s31.10 MB/s
Bun v1.1.26gzip15.29 MB/s10.11 MB/s
Bun v1.1.27inflate87.79 MB/s102.86 MB/s
Bun v1.1.26inflate50.72 MB/s43.83 MB/s
Node v22.5.1inflate26.07 MB/s74.64 MB/s
Bun v1.1.27inflateRaw87.68 MB/s101.78 MB/s
Bun v1.1.26inflateRaw53.89 MB/s43.13 MB/s
Node v22.5.1inflateRaw33.35 MB/s75.02 MB/s

透過 Linux x64 Hetzner 伺服器上的第三方 zlib 效能基準測試

Bun 中 node:zlib 的最佳化還有更多工作要做,但這是一個好的開始。

非常感謝 @nektro 實作此功能。

新指令:bun pm pack

bun pm pack 設計為 npm pack 的直接替代品。

Bun.serve() (HTTP 伺服器) 的新功能

此版本為我們的快速 HTTP 伺服器 Bun.serve() 引入了可靠性和生活品質的改進。

靜態路由

現在您可以傳遞 static 選項,為路徑提供靜態 Response 物件。

Bun.serve({
  static: {
    "/api/health-check": new Response("🟢"),
    "/old-link": Response.redirect("/new-link", 301),
    "/api/version": Response.json(
      {
        app: require("./package.json").version,
        bun: Bun.version,
      },
      {
        headers: {
          "X-Powered-By": "bun",
        },
      },
    ),
  },

  async fetch(req) {
    return new Response("Dynamic!");
  },
});

request.clone()response.clone() 中支援 ReadableStream

現在透過 request.clone()response.clone() 支援複製串流 RequestResponse

Bun.serve 複製請求

Bun.serve({
  async fetch(req, server) {
    const cloned = req.clone();
    await req.json();

    // Previously, this would be empty.
    await cloned.json();

    // ... rest of the code
  },
});

fetch 複製 Response

const response = await fetch("https://example.com");
const cloned = response.clone();

console.log(await response.text());
console.log(await cloned.text());

先前,僅當將字串、ArrayBuffer 或 Blob 傳遞給 Response 建構函式時,才支援靜態回應。

ReadableStream 中的 “cancel” 方法

當請求中止時,Bun 現在會呼叫 ReadableStream 中的 cancel 方法。

import { serve } from "bun";

serve({
  async fetch(req, server) {
    req.signal.addEventListener("abort", () => {
      // Previously, AbortSignal was the only way to detect if a request was aborted.
      console.log("Request aborted");
    });

    return new Response(
      new ReadableStream({
        async pull(controller) {
          controller.enqueue("Hello World");
          await Bun.sleep(1000);
        },
        cancel() {
          // New! Called when the request is aborted.
          console.log("Stream cancelled");
        },
      }),
    );
  },
});

每個請求的逾時

新的 server.timeout(request: Request, seconds: number) 方法允許您為每個特定的 HTTP 請求設定逾時。

為請求設定 60 秒逾時

Bun.serve({
  async fetch(req, server) {
    server.timeout(req, 60); // 60 seconds
    await req.formData();
    return new Response("Slow response");
  },
});

感謝 @cirospaciari 實作此功能。

更快的緩衝串流

此版本我們不只為 Bun.serve() 新增了功能。我們也使其速度更快。

新的 CLI 旗標:--max-http-header-size

傳遞 --max-http-header-size 會設定 HTTP 請求標頭緩衝區的大小。

https://github.com/oven-sh/bun/pull/13577

已修正:server.requestIPawait 之後

先前,在回呼或呼叫 await 之後使用 server.requestIP 會遺失請求中繼資料。此問題已修正。

Bun.serve({
  port: 3000,
  async fetch(req, server) {
    console.log(server.requestIP(req));
    // { address: '127.0.0.1', family: 'IPv4', ... }

    await req.formData();

    console.log(server.requestIP(req));
    //    now: { address: '127.0.0.1', family: 'IPv4', ... }
    // before: undefined
  },
});

已修正:在已關閉的 WebSocket 上 ws.publish

Bun.serve 中,在 websocket 上呼叫 .publish 會向所有用戶端傳送訊息,除了 websocket 本身。在 close 處理常式中使用此功能時,WebSocket 已關閉,且無法傳送訊息。此問題現在已修正。

感謝 @cirospaciari 修正此問題。

已修正:存取請求主體和緩衝方法時的記憶體洩漏

已修正以下程式碼中的記憶體洩漏

Bun.serve({
  async fetch(req) {
    if (req.body) {
      await req.json();
    }

    // ... rest of the code
  },
});

當存取 Request 主體的 ReadableStream 時,在某些情況下,諸如 req.json 之類的緩衝方法可能會使用不同的實作,並且在這些情況下,Request 物件會錯誤地持有對 req.json 傳回的 Promise 的強參考,導致記憶體洩漏。

在為串流新增 clone() 支援時,我們修改了 RequestResponse 的實作,以修正此問題和類似問題。

bun outdated 過濾

bun outdated 現在具有 --filter,可讓您選擇要稽核哪些工作區以檢查過時的套件。

# Path patterns:
# Matches all workspaces in `./packages`
bun outdated --filter="./packages/*"

# Name patterns:
# All workspaces with names starting with `pkg`
bun outdated --filter="pkg*"

# All workspaces excluding `pkg1`
bun outdated --filter="*" --filter="!pkg1"

此外,位置引數會過濾依賴項清單,如果您只想檢查特定套件的更新,這會很有幫助。

# All dependencies starting with `is-` (could display `is-even`, `is-odd`, ...)
bun outdated "is-*"

# All dependencies from a particular scope
bun outdated "@discordjs/*"

# With `--filter`. Matches all outdated `jquery` dependencies in all workspaces.
bun outdated jquery --filter="*"

bun run Ctrl + C 行為已修正

bun run 未將 POSIX 訊號從 bun 程序傳播到子程序(僅從子程序 -> 父程序)。這在某些情況下導致了奇怪的錯誤,例如 CTRL + C 無法退出子程序,直到稍後從斷開連線的終端機讀取 stdin 時發生 I/O 錯誤。這在視覺上表現為當您按下 ↑ 向上鍵時,出現 ^[[A 字元,而不是先前的指令。

此問題已修正。

感謝 @xales 偵錯此問題。

--watch--hot 中監看任意檔案類型

Bun 的內建監看和熱重載現在支援監看任意檔案類型。

若要監看檔案,請匯入它。

import "./tailwind.css";
// ... rest of my app

Bun 的監看器依賴模組圖來判斷哪些檔案會觸發重新載入。這減少了不必要的重新載入,縮短了您的迭代週期時間。

先前,僅監看 JavaScript、TypeScript、JSON、TOML 和 .txt 檔案。現在,Bun 將監看匯入的任何檔案,無論檔案副檔名為何。

已修正:預設 idleTimeout 不再於 node:http 中設定

在 Bun 1.1.26 中,預設的 idleTimeout 為 10 秒,這是一個重大變更,因為之前的版本具有無限逾時。idleTimeout 的預設值現在為 0,這會停用逾時。

Node.js 相容性改進

此版本還包含許多 Node.js 相容性改進。

已修正:從 N-API 擲回例外時當機

已修正當擲回例外時,N-API 中導致當機的錯誤。

已修正:存取堆積分配的 JSValue 時,N-API 中當機

JavaScriptCore 和 V8 是不同的引擎,它們使用不同的垃圾回收方法。JavaScriptCore 掃描堆疊。V8 依賴句柄作用域。

先前,Bun 未實作句柄作用域。這導致 DuckDB 等 N-API 套件在堆積分配 napi 值時未在堆疊記憶體中參考它們,從而導致當機。垃圾收集器看不到它們,並過早清理記憶體。

感謝 @190n 實作句柄作用域。

已修正:影響 Next.js 中介軟體的當機

已修正當在 node:vm 內部使用擴充內建類別(如 URLResponse)的類別時,node:vm 中的當機。此當機可在 Next.js 中介軟體中重現。

已修正:某些 Buffer 方法中缺少 ERR_INVALID_ARG_TYPE

Buffer.isAsciiBuffer.isUtf8 中,當給定無效引數時擲回的錯誤現在正確地包含 code: "ERR_INVALID_ARG_TYPE"

已修正:new URL 中缺少 ERR_INVALID_URL

為了與 Node.js 匹配,當給定無效 URL 時,new URL 擲回的錯誤現在包含 code: "ERR_INVALID_URL"

已修正:空訊息的 AES-GCM 加密

感謝 @wpaulino,空訊息現在可以在 AES-GCM 加密中正確地往返。

已修正:util.promisifycrypto.generateKeyPair

感謝 @wpaulino,在 crypto.generateKeyPair 上呼叫 util.promisify 現在將傳回正確的 promise 化函數。

已修正:處理 Buffer 中的記憶體不足錯誤

當將大型字串轉換為 Buffer 時,Bun 現在會透過擲回 OutOfMemoryError 而不是當機來處理記憶體不足錯誤。

已修正:node:tls 接受 TLS socket 的任意串流。已修正 mssql 套件

node:tls 中的 tls.connect 函數接受 socket 選項。這可讓您將任何 net.Socket 升級到 TLS。但是,此參數實際上可以是任何任意 stream.Duplex,Bun 先前不支持此參數,因為它依賴底層網路連線來更有效率地進行 TLS。

這解決了使用 mssql 套件時擲回 Error: socket must be an instance of net.Socket 的問題。

感謝 @cirospaciari

已修正:node:http agent 被忽略

在某些情況下,node:http agent 未被使用。此問題已修正。

感謝 @nektro

已修正:node:http setTimeout & server.setTimeout 被忽略

隨著 server.timeout 現在已實作,我們也在 node:http 中新增了對 server.setTimeoutrequest.setTimeout 的支援。

感謝 @cirospaciari 修正此問題。

已修正:node:vm 不一致性

已修正 node:vm 中的各種細微錯誤

  • vm.runInThisContext 現在在全球環境中運作
  • script.runInNewContext 現在在其自身的環境中運作
  • script.runInThisContextvm.runInThisContext 不將環境作為引數
  • vm.runInThisContextvm.runInContextvm.runInContext 將字串作為選項引數。

感謝 @SunsetTechuila 修正這些問題!

已修正:缺少 net.Socket.destroySoon

先前,node:net 中的此方法未定義。現在已修正。

fetch 可靠性改進

Windows 上 fetch() 中的 Proxy 現在運作更佳

在 Windows 上,使用 Proxy 搭配 fetch 通常會導致擲回 error: Syscall

感謝 @cirospaciari,此問題已解決。

已修正:FormDataURLSearchParams 主體的記憶體洩漏

在 Bun v1.1.25 中,引入了一個回歸錯誤,其中在 fetch() 請求的主體中傳送 FormDataURLSearchParams 會導致記憶體洩漏。此回歸錯誤現在已修正。

更多修正

已修正:讀取大型檔案 Bun.file 被截斷

當將超過 4gb 的檔案讀取到單個 ArrayBuffer 時,緩衝區會被截斷為 4gb。此問題現在已修正。

已修正:在某些終端機中清除螢幕

用於清除終端機螢幕的 ANSI 逸出碼已從 \x1b[H\x1b[2J 變更為 \x1B[2J\x1B[3J\x1B[H,這與更多終端機相容。最值得注意的是,這修正了 Visual Studio Code 的終端機,在此變更之前,該終端機未完全清除。

感謝 @jakebailey 修正此問題。

已修正:處理 Bun.escapeHTML 中的記憶體不足錯誤

當給予 Bun.escapeHTML 足夠大的字串時,它現在將擲回 OutOfMemoryError 而不是當機。

Bun.deepEquals 對於 MapSet 的效能改進

在 Bun v1.1.19 的 WebKit 升級之後,MapSet 的實作發生了變化,以至於我們不得不在 Bun.deepEquals 中移除它們的快速路徑。感謝 @wpaulino,新增了一個新的快速路徑,它比先前的位置更好。

此外,快速路徑涵蓋了擴充 MapSet 的自訂類別,使它們在 Bun.deepEquals 中的效能與基底類別本身幾乎沒有區別。

在 bun install 中,修復了在套件二進制檔案開啟時更新它們的問題

感謝 @dylan-conway

已修正:LCOV 報告器正確回報未命中行數

Bun 的 LCOV 報告器先前有時會回報 100% 行覆蓋率,即使並非總是如此。現在已修正,感謝 @fmorency

已修正:bun add -g 安裝後訊息

當安裝具有封鎖安裝後腳本的全域套件時,訊息現在將包含正確的指令

 $ bun install -g @delance/runtime
 bun add v1.1.27

 installed @delance/runtime@2024.8.103 with binaries:
  - delance-langserver

 68 packages installed [1.98s]

-Blocked 1 postinstall. Run `bun pm untrusted` for details.
+Blocked 1 postinstall. Run `bun pm -g untrusted` for details.

感謝 @RiskyMH 修復此問題

已修正:Bun.build 中的競爭條件

導致 Bun.build Promise 掛起的競爭條件已被修復。如果您在短時間內將許多 Bun.build 呼叫排隊,可能會導致此問題。

已修正:bun shell 未保持父程序存活

已修復以下程式碼會過早退出的錯誤,且不會印出 "never reached!!! why!!"。

import { $ } from "bun";
console.log("before shell");
(async function () {
  await `echo hi`;
  console.log("never reached!!! why!!");
})();

感謝 17 位貢獻者!