Bun

Bun v1.0.10


Jarred Sumner · 2023 年 11 月 7 日

Bun v1.0.10 修復了 14 個錯誤(解決了 102 個 👍 反應),node:http 效能提升了 14%,為 Linux ARM64 上的 Bun 增加了穩定性改進,並修復了 bun installnode:http 中的錯誤。

Bun 是一個極速的 JavaScript 執行環境、打包器、轉譯器和套件管理器 — 功能All-in-one。如果您錯過了,以下是一些 Bun 最近的變更

  • v1.0.0 - 首個穩定版本發布!
  • v1.0.1 - 為 .json 和 .toml 檔案提供具名導入,修復了 bun installnode:pathBuffer
  • v1.0.2 - 加快 --watch 速度和大量錯誤修復
  • v1.0.3 - emitDecoratorMetadata 和 Nest.js 支援,修復了私有 registry 和更多問題
  • v1.0.4 - server.requestIP、runtime plugins 中的虛擬模組,以及更多
  • v1.0.5 - 修復了 fetch() 的記憶體洩漏、node:crypto 模組中的 KeyObject 支援、bun:test 中的 expect().toEqualIgnoringWhitespace,以及更多
  • v1.0.6 - 修復了 3 個錯誤(解決了 85 個 👍 反應),在 package.json 中實作了 overrides & resolutions,並修復了影響 Docker 與 Bun 使用的迴歸問題
  • v1.0.7 - 修復了 59 個錯誤(解決了 78 個 👍 反應),在 bun install 中實作了可選的 peer dependencies,並改進了 Node.js 相容性。
  • v1.0.8 - 修復了 138 個錯誤(解決了 257 個 👍 反應),使 require() 使用的記憶體減少了 30%,為 bun test 新增了模組模擬,修復了更多 bun install 錯誤
  • v1.0.9 - 修復了 glibc 符號版本錯誤、非法指令錯誤、Bun.spawn 錯誤、peer dependency 安裝的邊緣案例,以及 JSX 轉譯器錯誤修復

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

node:http 效能提升 14%

Bun 的 node:http 實作目前包裝了 Bun.serve()Bun.serve() 建構於 Web 標準之上,例如 RequestResponse,這與 Node.js IncomingMessageServerResponse 類別不相容。這表示我們的包裝器必須做很多工作才能在這兩者之間轉換。

在修復幾個錯誤的同時,我們將一些先前在 TypeScript 中實作的包裝器程式碼移至原生程式碼。這稍微降低了包裝器的 overhead,使 node:http 效能提升了 14%。

hello world node:http
左:Bun v1.0.10。右:Bun v1.0.9

我想要細節

我們做了兩項變更來提升效能。

當您在 Bun 中執行 request.headers 時,我們會將來自 Bun 網頁伺服器的 headers 序列化為 Web 標準的 Headers 物件。通常,這很棒。但在這種情況下,node:http 僅使用它從 Web Headers 物件轉換為 Node.js headers 物件和 rawHeaders 陣列。Headers 物件在幕後做了很多額外的工作 - 連接字串、正規化空白等等,而 Node.js API 並沒有做這些。

當您在 Bun 中執行 request.url 時,它會解析 & 正規化與 Host header (如果可用) 連接的路徑名稱,產生一個絕對 URL 作為字串,您可以在 fetch 中使用,也可以與 URL 建構函式一起使用。在 Node.js 中,req.url 是一個字串,包含原始路徑和查詢字串 (/path?query)。它不是一個有效的 URL。我們做了很多額外的工作來產生一個有效的 URL 字串,然後再次解析它以轉換為路徑名稱 + 查詢字串。

現在,我們不再做所有這些工作:建立這些臨時物件 & 解析,我們現在只在本機程式碼中建立 Node.js headers 物件、rawHeaders 陣列和 url 字串。

作為將上述程式碼移至原生的副作用,我們也修復了一個錯誤,即在我們的 node:http 綁定中,多個 Set-Cookie headers 無法正確地暴露給 JavaScript。這導致了類似這樣的錯誤

undefined is not an object (evaluating 'header.toLowerCase')

已修復:「**」無法解析為 URL

在 Node 中,預期 IncomingMessage 可以接收無效的 URL 字串。先前,Bun 使用 URL 建構函式來解析、驗證和正規化傳入的 URL 字串,這導致了類似這樣的虛假錯誤

TypeError: "*" cannot be parsed as a URL.
      at new IncomingMessage (node:http:420:26)
      at fetch (node:http:383:26)
OPTIONS - * failed

現在,Bun 只是將 URL 字串傳遞給 node:http,這正是它所期望的。

Linux ARM64/Docker 版 Bun 的穩定性改進

您電腦上的大多數軟體都透過一個稱為「C 標準函式庫」的層與作業系統互動。C 標準函式庫是一組由您的作業系統實作的函式。例如,當您在 Bun 或 Node.js 中呼叫 fs.read 時,它最終會呼叫 C 標準函式庫中的 read 函式。該 read 函式可能只是包裝了 read 系統呼叫,這是一個由 Linux 核心 (或 macOS 上的 darwin 核心) 實作的函式。

在 Linux x64 和 arm64 上,Bun 通常會跳過 C 標準函式庫,直接使用 Linux 系統呼叫。這樣做速度會快一點,但也使得錯誤處理有時更加複雜,並且意味著我們需要花費更多時間來閱讀/理解內部結構。我們在 Linux arm64 上讀取錯誤的程式碼假設 libc errno 始終在使用中,但事實並非如此。簡而言之:我們有時在 Linux arm64 上錯誤地讀取了 errno

這導致了許多奇怪的問題,例如

docker-compose up

my-app-ui-1  | Failed to load PostCSS config: Failed to load PostCSS config (searchPath: /app): [EBADF] Bad file descriptor
my-app-ui-1  | undefined
my-app-ui-1  |    code: "EBADF"
my-app-ui-1  |  syscall: "fstat"
my-app-ui-1  |    errno: -9
my-app-ui-1  |

或者像這樣

#8 [4/4] RUN bun install
#8 0.077 bun install v1.0.9 (98f20170)
#8 0.077 error: Unexpected installing typescript
#8 0.077 error: Unexpected installing bun-types
#8 0.077 Failed to install 2 packages
#8 0.078 [2.00ms] done
#8 DONE 0.1s

此版本修復了這些問題。

已修復:在 macOS 上 bun:sqlite 中載入擴充功能

一個錯誤導致 Bun 不支援在 macOS 上 bun:sqlite 模組中載入擴充功能。這已得到修復,感謝 @paulbaumgart

已修復:bun install 中 pre-release 版本的 Semver 解析錯誤

Bun 為 bun install 實作了與 node-semver 相容的解析器。

在解析包含帶有 dist-tag 的 pre-release 版本的無效 semver 字串時,存在一個邊緣案例,可能會導致 Bun 崩潰。此問題已得到修復(感謝 @dylan-conway),並且我們新增了更多測試覆蓋率。

雜項

我們也更新到最新版本的 simdutf。

感謝 4 位貢獻者

完整變更日誌:bun-v1.0.9...bun-v1.0.10