Bun

Bun v1.0.18


Jarred Sumner · 2023 年 12 月 14 日

Bun v1.0.18 修復了 27 個錯誤(解決了 28 個 👍 反應)。已修復影響 create-vite 和 create-next 以及 stdin 的卡頓問題。已修復生命週期腳本回報「找不到 node」或「node-gyp」的問題。expect().rejects 現在的運作方式與 Jest 相同,以及更多錯誤修復。

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

  • v1.0.13 - 修復了 6 個錯誤(解決了 317 個 👍 反應)。現在 'http2' 模組和 gRPC.js 可以正常運作。Vite 5 和 Rollup 4 可以正常運作。實作 process.report.getReport(),改善對 ES5 'with' 語句的支援,修復 bun install 中的回歸錯誤,修復列印例外時的崩潰問題,修復 Bun.spawn 錯誤,以及修復 peer dependencies 錯誤
  • v1.0.14 - Bun.Glob,一個使用 glob 模式比對檔案和字串的快速 API。它也修復了在 bun install 期間提取依賴項時的競爭條件,改善了 node_modules 中的 TypeScript 模組解析,並使錯誤訊息更易於閱讀。
  • v1.0.15 - 修復了 23 個錯誤(解決了 117 個 👍 反應),tsc 啟動速度快了 2 倍。穩定的 WebSocket 客戶端、語法突顯的錯誤、更清晰的堆疊追蹤、使用 expect.extend() 新增自訂測試匹配器 + 其他 expect 匹配器。
  • v1.0.16 - 修復了 49 個錯誤(解決了 38 個 👍 反應)。Bun.file 和 Bun.write 的並行 IO 速度提升了 3 倍,現在支援 Google Cloud Run 和 Vercel,Bun.write 會自動建立父目錄(如果不存在),expect.extend 在 preload 內部可以正常運作,napi_create_object 速度提升了 2.5 倍,修復了影響 Astro v4 和 p-limit 的模組解析錯誤,console.log 錯誤修復
  • v1.0.17 - 修復了 15 個錯誤(解決了 152 個 👍 反應)。bun install postinstall 腳本適用於前 500 個套件,bunx supabase 啟動速度比 npx supabase 快 30 倍,bunx esbuild 啟動速度比 npx esbuild 快 50 倍,以及 bun install 的錯誤修復

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

已修復:從 process.stdin 讀取時卡頓的問題

已修復 Bun.stdin.stream()process.stdin 在第一次讀取後有時會卡頓的錯誤,感謝 @paperclover

此錯誤影響了許多套件,包括 create-vitecreate-next-app。當它提示使用者輸入時,終端機會在第二個提示時凍結。

bun 會卡住的地方

這是由與我們 process.stdin 實作相關的兩個錯誤所導致,process.stdin 是建立在 Bun.stdin.stream() 之上

  1. 我們之前在 ReadableStream 輸入上呼叫了 cancel,關閉了串流並阻止了接收新資料的能力。修復方法是改用 releaseLock
  2. 一個錯誤是,在呼叫 releaseLock 後,Bun 會認為串流仍然「在使用中」,這會使進程永遠保持活動狀態。

此問題已修復,感謝 @paperclover

已修復:生命週期腳本在錯誤的工作目錄中執行的問題

已修復生命週期腳本有時會在錯誤的工作目錄中執行的錯誤。此錯誤由 @dylan-conway 修復。

已修復:生命週期腳本回報找不到命令「node」或「node-gyp」的問題

昨天在 Bun v1.0.17 中,我們為 npm 上前 500 個套件啟用了生命週期腳本。雖然我們自己做了大量的測試,但我們遺漏了一些使用者回報的案例。

例如,如果沒有安裝 node-gyp 會發生什麼事?

bun install
node-gyp rebuild
Command not found: node-gyp

那可不好。我們已經修復了這個問題。現在,如果未安裝 node-gyp,Bun 會將 node-gyp 符號連結到執行 bunx node-gyp(這將延遲自動安裝 node-gyp)。

或者,如果您使用的生命週期腳本依賴於 node,但您在 Docker 中執行,且容器未安裝 node 呢?

bun install
node install.js
Command not found: node

那也不好。現在,如果未安裝 node,Bun 會將 node 符號連結到執行 bun

這些問題已修復,感謝 @dylan-conway

node 符號連結到 bun 的效果更佳

node 不可用時,Bun 會自動將 node 符號連結到 bun,以確保預期 node 存在的腳本仍然可以運作。但是,Bun 的 CLI 與 Node 的 CLI 非常不同,因此當執行 node buildnode install 等命令時,預期會找到類似 build.js 的檔案,而不是調用打包器或套件管理器。

之前

ln -s $(which bun) node && chmod +x node
./node build
bun build v1.0.18 (a648ed9e)
error: Missing entrypoints. What would you like to bundle?

Usage:
  $ bun build <entrypoint> [...<entrypoints>] [...flags]

To see full documentation:
  $ bun build --help

現在

./node build
Hello! (Bun 1.0.18)
build.js
const isBun = typeof Bun !== 'undefined';
const name = isBun ? "Bun" : "Node";
const version = isBun ? Bun.version : process.version;
console.log(`Hello! (${name} ${version})`)

感謝 @paperclover

重新連結是檔案的寫入時複製副本。它們使複製檔案的速度更快。macOS 自 2017 年 APFS 發布以來一直支援重新連結。Linux 在 brtfs 中支援重新連結,最近更多檔案系統新增了對重新連結的支援。

Bun 已經在 Linux 上使用 copy_file_range 來加快複製檔案的速度,但某些 Hypervisor(如 gVisor)會禁用此系統調用。現在 Bun 將嘗試使用 ioctl_ficlone,這是一個更低階的系統調用,其內部執行與 copy_file_range 非常相似的操作。ioctl_ficlone 的整體支援度不如 copy_file_range,但當 copy_file_range 不可用時,它是一個有用的備用方案。

copy_file_range 被禁用但 ioctl_ficlone 可用時,您會注意到以下項目的速度有所提升

  • bun install
  • fs.copyFilefs.copyFileSync
  • fs.cpfs.cpSync

若要強制使用 ioctl_ficlone,您可以將 constants.COPYFILE_FICLONE_FORCE 作為 flags 參數傳遞給 fs.copyFilefs.cp

import { copyFileSync, constants } from "fs";

copyFileSync("src/index.js", "dest/index.js", constants.COPYFILE_FICLONE_FORCE);

如果 ioctl_ficlone 不可用,這將拋出錯誤。

已修復:萬用字元 tsconfig 路徑未包含後綴的問題

已修復由於未新增後綴而導致萬用字元 tsconfig.json paths 無法解析的錯誤

error: Cannot find module "@faasjs/bar" from ".../test/js/bun/resolve/resolve-test.js"

感謝 @james-elicx 修復此問題。

已修復:expect().rejects.toThrow 的運作方式更像 Jest

在 Jest 中,expect().toThrow 需要您傳遞一個要呼叫的函數。使用 expect().rejects.toThrow,它們讓您可以簡單地傳入拒絕 Promise。Bun 不支援這種情況。

以下測試現在在 bun:test 中通過

rejects-toThrow.test.js
test("rejects to octopus", async () => {
  const rejection = Promise.reject(new Error("octopus"));
  await expect(rejection).rejects.toThrow("octopus");
});

感謝 @paperclover 修復此問題。

感謝 10 位貢獻者!