Bun

Bun v1.0.29


Jarred Sumner · 2024 年 2 月 23 日

Bun 是一個難以置信地快速的 JavaScript 執行時、打包器、轉譯器和套件管理器 — 功能All-in-one。

此版本修復了 8 個錯誤。Bun.stringWidth(a) 是廣受歡迎的 "string-width" 套件的極速替代品,速度快約 6,756 倍。bunx 現在更頻繁地檢查更新。在 bun:test 中新增了 expect().toBeOneOf()。修復了影響 Prisma 的記憶體洩漏。Shell 現在支援進階重新導向,例如 2>&1&>。提升了 bunx、bun install、WebSocket 客戶端和 Bun Shell 的可靠性

先前的版本

  • v1.0.28 修復了 6 個錯誤(解決了 26 個 👍 反應)。修復了影響 Prisma 和 Astro、node:eventsnode:readlinenode:http2 的錯誤。修復了 Bun Shell 中涉及 stdin 重新導向的錯誤,以及 bun:testtest.eachdescribe.only 的錯誤。
  • v1.0.27 修復了 72 個錯誤(解決了 192 個 👍 反應),Bun Shell 支援在非零退出代碼時拋出錯誤、使用非同步生成器串流 Response body、提高了 fetch()、http2 客戶端、Bun.Glob 的可靠性。修復了 Linux 上 bun --watch 的回歸問題。提升了 Node.js 相容性
  • v1.0.26 修復了 30 個錯誤(解決了 60 個 👍 反應),在 bun:sqlite 中新增了對多語句查詢的支援,使 bun --watch 在長時間運行的會話中更可靠,Bun.FileSystemRouter 現在支援超過 64 個路由,修復了 expect().toStrictEqual() 的錯誤,修復了 2 個 error.stack 的錯誤,提升了 Node.js 相容性

安裝 Bun

curl
npm
brew
docker
curl
curl -fsSL https://bun.dev.org.tw/install | bash
npm
npm install -g 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

bunx 更頻繁地檢查更新

bunx 類似於 npx,但由 bun install 提供支援。它的啟動速度比 npx 快 100 倍

bunx 中的快取失效錯誤導致它沒有像應該的那樣頻繁地檢查更新。現在我們依靠 stat 中的時間戳來判斷自上次檢查以來是否已過去 24 小時,這樣更可靠。

我們也進行了修改,因此明確使用標籤(例如 bunx create-vite@latest)將始終檢查最新版本,並在先前安裝的版本存在時將其刪除。

感謝 @paperclover 修復此問題。

Bun.stringWidth() ~6,756 倍速於 "string-width" 替代品

Bun.stringWidth(string) 傳回字串在終端機中的可見寬度。當您想知道字串在終端機中將佔用多少列時,這非常有用。

import { stringWidth } from "bun";

// text
console.log(stringWidth("hello")); // => 5

// emoji
console.log(stringWidth("👋")); // => 2

// ansi colors
console.log(stringWidth("\u001b[31mhello\u001b[39m")); // => 5

// fullwidth characters
console.log(stringWidth("你好")); // => 4

// graphemes
console.log(stringWidth("👩‍👩‍👧‍👦")); // => 2

它考慮了 ANSI 逸出碼全形字元、字素和表情符號。它支援 Latin1、UTF-16 和 UTF-8 編碼,並針對每種編碼進行了最佳化實作。

string-width 套件每週下載量超過 1 億次。使其成為 Bun 的內建函式意味著您無需為此常見用例安裝額外的套件,並且讓我們能夠對其進行最佳化。非常感謝 @sindresorhus 建立 string-width,並感謝他啟發我們將其納入 Bun 中。

在此基準測試中,對於超過 500 個字元的 ascii 輸入,Bun.stringWidth 的效能比 string-width 快約 6,756 倍。範圍從最壞情況下的 48 倍快到 25,000 個 ascii 或 ansi 字元的 137,623 倍快。

❯ bun string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: bun 1.0.29 (x64-linux)

benchmark                                          time (avg)             (min … max)       p75       p99      p995
------------------------------------------------------------------------------------- -----------------------------
Bun.stringWidth     500 chars ascii              37.09 ns/iter   (36.77 ns … 41.11 ns)  37.07 ns  38.84 ns  38.99 ns

❯ node string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: node v21.4.0 (x64-linux)

benchmark                                          time (avg)             (min … max)       p75       p99      p995
------------------------------------------------------------------------------------- -----------------------------
npm/string-width    500 chars ascii             249,710 ns/iter (239,970 ns … 293,180 ns) 250,930 ns  276,700 ns 281,450 ns

為了使 Bun.stringWidth 快速,我們使用最佳化的 SIMD 指令在 Zig 中實作了它,同時考慮了 Latin1、UTF-16 和 UTF-8 編碼。它實作了與 string-width 相同的 API 並通過了他們的測試。這也修復了 console.table 中的一個邊緣案例。感謝 @nektro 實作此功能!

檢視完整基準測試

expect(a).toBeOneOf([a, b, c])bun:test

bun:test 獲得了一個新的匹配器:toBeOneOf。當您想檢查值是否為值列表之一時,這非常有用。

import { test, expect } from "bun:test";

test("my test here", () => {
  expect(1).toBeOneOf([1, 2, 3]);
});

流行的 jest-extended 套件也支援此匹配器。

這與 expect(a).toInclude(b) 有何不同?

expect(a).toInclude(b) 檢查 a 是否包含 bexpect(a).toBeOneOf([a, b, c]) 檢查 a 是否為 [a, b, c] 之一。toBeOneOf 對實際值進行操作,而 toInclude 對預期值進行操作。

import { test, expect } from "bun:test";

test("my test here", () => {
  expect([1, 2, 3]).toInclude(1);
  expect(1).toBeOneOf([1, 2, 3]);
});

當目標是檢查值是否為值列表之一時,toBeOneOf 更具可讀性,並在失敗時提供更好的錯誤訊息。

Shell 支援進階重新導向,例如 2>&1&>

Bun Shell 現在支援進階重新導向,例如 2>&1&>

若要將 stderr 輸出到 stdout,您可以使用 2>&1

import { $ } from "bun";

await $`vite build 2>&1 output.txt`;

若要重新導向 stdout 和 stderr,您可以使用 &>

import { $ } from "bun";

await $`next build &> output.txt`;

我們也新增了對 2>> 的支援,以附加 stderr。

感謝 @zackradisic 實作此功能。

已修復:bun install semver 預發布版本錯誤

已修復 bun install 有時無法正確解析 node-semver 正確解析的預發布版本的邊緣案例。

此錯誤影響了 svelte-eslint-parser 套件,並出現類似以下的錯誤

error: No version matching ">=0.34.0-next.4 <1.0.0" found for specifier "svelte-eslint-parser"

感謝 @dylan-conway 修復此問題。

已修復:WebSocket 客戶端短訊息錯誤

已修復有效負載為 1 或 2 個位元組的訊息有時會在 WebSocket 客戶端中導致逾時的錯誤。此錯誤不會影響 WebSocket 伺服器。感謝 @lithdew 修復此問題。這是 @lithdew 對 Bun 的第一個 PR,但我們已經在 Bun 的許多地方使用了 @lithdew 的開放原始碼一段時間了。

已修復:napi 中影響 Prisma 的記憶體洩漏

已修復 napi(影響 Prisma)中的記憶體洩漏。

在微基準測試中,它將記憶體使用量從 1720 MB 減少到 275 MB(減少了 6 倍)。

感謝 @camero2734 修復此問題。

已修復:response.blob() 中的記憶體洩漏回歸

已修復 Bun v1.0.26 中引入的導致 response.blob() 中記憶體洩漏的回歸。感謝 @nektro 修復此問題!

已修復:Bun.password.verify 在搭配 bcrypt 的長密碼上

bcrypt 的最大密碼長度為 72 個字元。這也是 Bun.password.hash 預設為更現代的 Argon2 演算法的部分原因。

為了補償 bcrypt 中的最大密碼長度,當 algorithm 設定為 bcrypt 且密碼長度超過 72 個字元時,Bun.password.hash 會對密碼輸入使用 SHA-512,並將 SHA-512 hash 傳送給 bcrypt(SHA-512 的選擇是由流行的 libsodium 密碼編譯程式庫的作者建議的)。

但是,當密碼長度超過 72 個字元且演算法設定為 bcrypt 時,我們沒有對 Bun.password.verify 執行此操作。這表示您可能會遇到 Bun.password.verify 對先前使用 Bun.password.hash 雜湊的密碼傳回 false 的情況。

已修復此問題,因此當密碼長度超過 72 個字元時,使用 bcrypt 時,Bun.password.verify 現在的行為與 Bun.password.hash 相同。感謝 @argosphil 修復此問題。

有時,發布到 npm 的套件會在子目錄中包含 vendored node_modules 目錄(通常是意外)。先前,bun install 在使用硬連結安裝時會忽略這些 vendored node_modules 資料夾,這破壞了依賴此行為的套件。我們已修復此問題,因此 bun install 不再忽略 vendored node_modules 資料夾。

感謝 @eemelipa 修復此問題。

已修復:Shell 替換錯誤新增額外空格字元

先前,Bun Shell 中的以下程式碼會新增額外空格字元

echo $(echo id)/$(echo region) # => "id / region"

現在它正確地輸出

echo $(echo id)/$(echo region) # => "id/region"

感謝 @zackradisic

已修復:Shell latin1 範本編碼錯誤

已修復 Bun Shell 有時會錯誤處理非 ascii latin1 字元的錯誤。感謝 @zackradisic

已修復:bunx 在同一部機器上有多個使用者時

bunx 現在在同一部機器上的多個使用者使用它時可以正常運作。由於 bunx 將其快取儲存在暫存目錄中,因此同一部機器上的多個使用者共用同一個快取目錄。這有時會導致權限問題。我們已透過在快取金鑰中包含 uid 來修復此問題,以便不同的使用者不會共用同一個快取。

感謝 @paperclover 修復此問題。

Bundows 即將推出

我們將繼續致力於 Windows 支援。Bun v1.1 將支援 Windows。

感謝 8 位貢獻者!