Bun
    Bun

Bun v0.8.0


Colin McDonnell · 2023 年 8 月 24 日

Bun v0.8.0 新增了偵錯器支援,實作了 fetch 串流,並解鎖了 SvelteKit。實作了來自 node:tty 的 ReadStream 和 WriteStream,且 .setRawMode() 現在可在 process.stdin 上運作,解鎖了數個互動式 CLI 工具。此外還有 Node.js 相容性更新、錯誤修正和穩定性改善。

Bun 1.0 即將在 9 月 7 日推出!請在 https://bun.dev.org.tw/1.0 註冊以收看發佈直播。

Bun 是一個速度極快的 JavaScript 執行階段、打包器、轉譯器和套件管理器 — 功能All-in-One。我們最近發佈了很多 Bun 的變更。以下是最近幾個版本的重點回顧。以防您錯過了

  • v0.7.0 - Web Workers、--smolstructuredClone()、WebSocket 可靠性改善、node:tls 修正及更多。
  • v0.7.1 - ES Modules 載入速度提升 30-250%、fs.watch 修正及許多 node:fs 相容性改善。
  • v0.7.2 - 實作 node:worker_threadsnode:diagnostics_channelBroadcastChannel
  • v0.7.3 - bun test 中的覆蓋率報告,以及使用 bun test -t 進行測試篩選。

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

偵錯器支援

Bun 現在透過 WebKit 的 Inspector Protocol 實作偵錯器支援。若要使用,請使用 --inspect 旗標執行您的檔案或指令碼。考量以下簡單的 HTTP 伺服器。

server.ts
const server = Bun.serve({
  fetch(req){
    console.log(req.url);
    return new Response("Hello world!");
  }
});

console.log(`Listening on https://127.0.0.1:${server.port}`);

當我們使用 --inspect 執行此檔案時,它會啟動我們的 HTTP 伺服器在未使用的連接埠上啟動 localhost WebSocket 伺服器。此 WebSocket 伺服器使用 Inspector Protocol 與偵錯工具通訊,偵錯工具可以內省和控制正在執行的 bun 程序。

bun --inspect server.ts
Listening on https://127.0.0.1:3000
------------------ Bun Inspector ------------------
Listening at:
  ws://127.0.0.1:6499/0tqxs9exrgrm

Inspect in browser:
  https://debug.bun.sh/#localhost:6499/0tqxs9exrgrm
------------------ Bun Inspector ------------------

使用 debug.bun.sh

--inspect 旗標也會在主控台中列印 https://debug.bun.sh# URL。網域 debug.bun.sh 託管了 Safari Developer Tools 的精簡版本,專為 Bun 偵錯而設計。在您偏好的瀏覽器中開啟連結,新的偵錯工作階段將自動開始。

Bun Developer Tools(位於 debug.bun.sh)

從網頁偵錯器,您可以檢查目前正在執行的程式碼並設定中斷點。一旦觸發中斷點,您可以

  • 檢視範圍內的所有變數
  • 在主控台中執行程式碼,完全存取範圍內的變數和 Bun API
  • 逐步執行您的程式碼
screenshot of Bun debugger

請參閱 使用網頁偵錯器偵錯 Bun 指南以取得更完整的說明文件。

bun update

新的 bun update 命令會將所有專案依賴項更新為與您 package.json 中的語意版本範圍相容的最新版本。

bun update

若要更新特定的依賴項

bun update zod

注意 — 與 npm 不同,bun upgrade 命令保留用於升級 Bun 本身。它不是 bun update 的別名。

感謝 @alexlamsl 實作此功能。

SvelteKit 支援

改善對 Worker 中的環境變數 的支援,已解鎖 SvelteKit。使用 create-svelte 建立您的專案骨架。

bunx create-svelte my-app
create-svelte version 5.0.5

┌  Welcome to SvelteKit!

◇  Which Svelte app template?
│  SvelteKit demo app

◇  Add type checking with TypeScript?
│  Yes, using TypeScript syntax

◇  Select additional options (use arrow keys/space bar)
│  none

└  Your project is ready!

✔ Typescript
  Inside Svelte components, use <script lang="ts">

Install community-maintained integrations:
  https://github.com/svelte-add/svelte-add

若要安裝依賴項並啟動開發伺服器

cd my-app
bun install
bun run dev -- --open

開啟 localhost:3000 以查看運作中的 SvelteKit 示範應用程式。

在 Bun 上執行的 SvelteKit 應用程式

Nuxt 支援 (nuxt dev)

透過改善 node:ttynode:fs 支援,Nuxt 開發伺服器現在可與 Bun 執行階段搭配使用。若要開始使用,請使用 nuxi 命令列工具。

bunx --bun nuxi init my-app
cd my-app
bun install

安裝依賴項後,使用 "dev" package.json 指令碼啟動開發伺服器。

bun --bun run dev
 $ nuxt dev
Nuxt 3.6.5 with Nitro 2.5.2
  > Local:    https://127.0.0.1:3000/
  > Network:  http://192.168.0.21:3000/
  > Network:  http://[fd8a:d31d:481c:4883:1c64:3d90:9f83:d8a2]:3000/

✔ Nuxt DevTools is enabled v0.8.0 (experimental)
ℹ Vite client warmed up in 547ms
✔ Nitro built in 244 ms

--bun 旗標確保伺服器使用 Bun 執行階段而不是 Node.js。依預設,nuxt CLI 使用 Node.js。

然後瀏覽 https://127.0.0.1:3000 以查看預設的 Nuxt 歡迎畫面。

在 Bun 上執行的 Nuxt 應用程式

注意 — Nuxt 的 build 命令仍有一些問題。在執行生產建置時,請使用 bun run build 而不是 bun --bun run build。這會使用 Node.js 執行 Nuxt 的建置管線。請在此處追蹤此問題 here

請參閱 使用 Nuxt 和 Bun 建置應用程式 以取得更完整的逐步解說。

Fetch 回應主體串流

感謝 @cirospaciari,Bun 現在實作了 fetch() 回應主體串流。這表示您現在可以從 fetch 回應串流資料,而無需等待下載整個回應。

const res = await fetch("https://example.com/bigfile.txt");

// read the response chunk-by-chunk!
for await (const chunk of res.body) {
  console.log(chunk);
}

在 Bun 中使用 OpenAI

當使用需要較長時間才能回應的 API 時,串流特別有用。現在您可以在 Bun 中串流來自 OpenAI API 的回應。

import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: "my api key",
});

const stream = await openai.chat.completions.create({
  model: "gpt-4",
  messages: [{ role: "user", content: "Say this is a test" }],
  stream: true,
});

for await (const part of stream) {
  process.stdout.write(part.choices[0]?.delta?.content || "");
}

Bun.serve() 串流改善

先前,以下程式碼會緩衝回應主體,表示它只會在產生整個主體後才傳送回應。

import { serve, sleep } from "bun";
serve({
  fetch(req) {
    return new Response(
      new ReadableStream({
        async pull(controller) {
          for (let i = 0; i < 20; i++) {
            controller.enqueue("Hello world!");
            await sleep(42);
          }

          controller.close();
        },
      }),
    );
  },
});

// Hello World!Hello World!Hello World!...[~840ms]

這不是人們想要的!現在,回應主體會進行串流,表示它會在產生時傳送至用戶端。

import { serve, sleep } from "bun";
serve({
  fetch(req) {
    return new Response(
      new ReadableStream({
        async pull(controller) {
          for (let i = 0; i < 20; i++) {
            controller.enqueue("Hello world!");
            await sleep(42);
          }

          controller.close();
        },
      }),
    );
  },
});

// Hello world! [42ms]
// Hello world! [42ms]
// Hello world! [42ms]

先前,僅在使用 ReadableStream 且 type: "direct" 時才支援串流,這是 Bun 特有的快速串流路徑。

import { serve, sleep } from "bun";
serve({
  port: 3000,
  fetch(req) {
    return new Response(
      new ReadableStream({
        // bun specific option
        type: "direct",

        async pull(controller) {
          for (let i = 0; i < 20; i++) {
            controller.write("Hello world!");

            // in bun < 0.8.0, flush() was required
            controller.flush();

            // now bun will automatically flush pending writes once the microtask queue is drained
            await sleep(42);
          }

          controller.end();
        },
      }),
    );
  },
});

// Hello world! [42ms]
// Hello world! [42ms]
// Hello world! [42ms]
// Hello world! [42ms]

我們還有最佳化工作要做,以使使用預設 ReadableStream 類型的串流變得快速。目前,我們建議使用 type: "direct" 以獲得最快的串流速度。

支援 node:ttyprocess.stdin.setRawMode()

Bun 中的 Inquirer npm 套件

已實作來自 node:ttyReadStreamWriteStream 類別,且 process.stdin 現在是 ReadStream 的執行個體。因此,現在可以在 process.stdin 上啟用「原始模式」。

process.stdin.setRawMode(true);

支援 inquirer 和其他提示程式庫

這使得無需等待換行字元即可讀取按鍵輸入,這對於互動式 CLI 工具非常重要。現在完全支援熱門程式庫 inquirerenquirerprompts

執行以下命令以使用 Bun 和互動式 create-remix 命令列工具互動式地建立 Remix 應用程式骨架。

bunx --bun create-remix

感謝 @dylan-conway 實作此功能。

bun test 的改善

test.eachdescribe.each

感謝 @jecquas,Bun 現在支援 Jest 中的 test.eachdescribe.each。這使得使用不同輸入執行相同測試變得容易。

describe.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])("add(%i, %i)", (a, b, expected) => {
  test(`returns ${expected}`, () => {
    expect(a + b).toBe(expected);
  });
});

.toSatisfy().toIncludeRepeated()

感謝 @TiranexDevbun test 現在支援 其他匹配器。這些匹配器是 jest-extended 的一部分,現在由 bun test 原生支援。

.toSatisfy() 的範例用法

const isOdd = (value: number) => value % 2 !== 0;
it("toSatisfy", () => {
  expect(1).toSatisfy(isOdd);
  expect(2).not.toSatisfy(isOdd);
});

.toIncludeRepeated() 的範例用法

test("toIncludeRepeated", () => {
  // check if string contains substring exactly 2 times
  expect("hello hello").toIncludeRepeated("hello", 2);
  // works with .not
  expect("hello hello world").not.toIncludeRepeated("hello", 1);
});

速度提升 40 倍的 buffer.toString("hex")

Node.js Buffer.toString("hex") 函數透過 SIMD 進行最佳化,效能提升 40 倍。

Bun.inspect.custom

現在可以使用 Bun.inspect.custom 符號來擴增物件,以使用自訂格式器。基於相容性考量,Node.js node:util 中的 util.inspect.custom 也適用。

class Password {
  value: string;
  constructor(value: string) {
    this.value = value;
  }
  [Bun.inspect.custom]() {
    return "Password <********>";
  }
}

const p = new Password("secret");
console.log(p);
// => "Password <********>"

全域 File 建構函式

已新增 File 建構函式作為新的全域變數。可以建構 File 執行個體。

const file = new File(["hello world"], "hello.txt", {
  type: "text/plain",
  lastModified: Date.now() - 1000,
});

file.size; // 11
file.name; // "hello.txt"
file.type; // "text/plain"
file.lastModified; // 1693597759310573

已修正 Buffer 相關函數中的 JIT 當機問題。此當機是由傳遞至 DOMJIT 時不正確的副作用所造成,這會在呼叫函數時導致類型驗證期間當機。這影響了數個程式庫,且當機在 Bun v0.7.3 中的 JavaScriptCore 升級後開始發生。

在足夠多次呼叫 Buffer.allocBuffer.allocUnsafeBuffer.isBuffer 後,此當機會導致擲回 EXC_BREAKPOINT

錯誤修正和穩定性改善

Buffer.toString("hex") 記憶體洩漏修正

修正 buffer.toString("hex") 實作中的記憶體洩漏問題。

NAPI 修正和 resvgsharp 支援

已修正 NAPIClass 建構函式napi_create_external_arraybuffer / napi_create_external_buffer 中的幾個錯誤。這解決了使用 resvg-jssharp 時的問題。

this 無效時,提供更佳的錯誤訊息

當使用非預期的 this 值呼叫方法時,Bun 現在會報告 資訊豐富的錯誤訊息。

const { json } = new Response(`"hello"`);
json();
// ^ TypeError: Expected `this` to be instanceof Response

處理跨裝置檔案複製

Bun 現在會偵測 檔案複製作業 (例如 fs.copyFile) 何時嘗試跨裝置或分割區複製檔案,並回復為手動檔案複製系統呼叫。

修正 Bun.deepEqual URL 比較

#4105 修正了 URL 未透過其內部 href 正確比較的錯誤。

已修正 macOS 上 async-await 效能的 10% 衰退問題

  • 日光節約時間快取不再於每個微任務呼叫時更新。此衰退從 v0.7.x 開始發生。

數個串流修正

#4251 包含 ReadableStream 實作中的許多改善和錯誤修正。這包括

  • 一旦微任務佇列已排空,HTTP 回應主體的擱置寫入會自動刷新,修正 #1886
  • 改善 pull 內部的錯誤處理。

變更記錄

隨著 Bun 1.0 即將推出,我們一直在追蹤剩餘的記憶體洩漏和當機問題。

#4028[install] 正確處理現有 peerDependenciesbun add,作者:@alexlamsl
#4026執行遺失的指令碼會以非 0 結束,作者:@YashoSharma
#4030繫結 require.resolve`()`,作者:@Jarred-Sumner
#4034正規化 Request URL,作者:@Jarred-Sumner
#4042修正 path.normalize 邊緣案例。作者:@Hanaasagi
#4043將 Bun 的轉譯器編譯為 WASM 並新增測試分析器,作者:@Jarred-Sumner
#4048修正使用 set-cookie 逐一查看標頭的問題,作者:@dylan-conway
#4000實作擷取資料 URL,作者:@dylan-conway
#4054修正 Bun.hash 函數,作者:@jhmaster2000
#4064修正 path.format 相容性問題。作者:@Hanaasagi
#4073修正 require("console") #3820,作者:@paperclover
#4076在使用者建構的 CommonJSModuleRecords 中將 exports 設定為 {},作者:@paperclover
#4086修正 XLSX.read 核心傾印問題,作者:@Hanaasagi
#4027新增 bun --revision 支援,作者:@YashoSharma
#4106修正 base64url 編碼器中的區段錯誤 #4062,作者:@Jarred-Sumner
#4109處理 setInterval 的群體性湧入問題,作者:@Jarred-Sumner
#4111修正 Buffer.toString('base64url') 中的記憶體洩漏問題,作者:@Jarred-Sumner
#4113執行沒有副檔名的檔案,作者:@dylan-conway
#4117astro build 稍微快一點
#4125支援 TypeScript 的 export type * as Foo from 'bar',作者:@Jarred-Sumner
#4126bun-wasm 修正和改善,作者:@jhmaster2000
#4131棄用載入 node_modules.bun,作者:@Jarred-Sumner
#4129修正自訂組態路徑無法運作的問題。作者:@Hanaasagi
#4114修正 worker 事件迴圈 ref/unref + 洩漏問題,作者:@paperclover
#4152讓內建來源起點使用有效的 url,作者:@paperclover
#4155修正匯入過長字串的問題,作者:@paperclover
#4162修正方法名稱錯字,作者:@Hanaasagi
#4157修正 Bun.connect 的事件迴圈問題,作者:@paperclover
#4172更新文件以說明我們目前的節點相容性狀態,作者:@paperclover,位於 https://github.com/oven-sh/bun/pull/4172
#4173建立 domjit.test.ts,作者:@dylan-conway,位於 https://github.com/oven-sh/bun/pull/4173
#4150修正 prisma linux 產生問題,作者:@cirospaciari,位於 https://github.com/oven-sh/bun/pull/4150
#4181修正洩漏 .ptr 問題,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4181
#4192更正指南的 bunfig 範例選項,作者:@xxxhussein,位於 https://github.com/oven-sh/bun/pull/4192
#4193重構:將 HTMLRewriter 移至 c++ 繫結,作者:@bru02,位於 https://github.com/oven-sh/bun/pull/4193
#4191Fix(node:fs): 在 fs.read 回呼中新增 buffer 參數。作者:@Hanaasagi,位於 https://github.com/oven-sh/bun/pull/4191
#4154允許覆寫 IncomingRequest.req。作者:@paperclover,位於 https://github.com/oven-sh/bun/pull/4154
#4098支援 Nitro,作者:@paperclover,位於 https://github.com/oven-sh/bun/pull/4098
#4194util.inspect.custom 支援新增至 util.inspect/Bun.inspect/console.log,作者:@paperclover,位於 https://github.com/oven-sh/bun/pull/4194
#4187移除大部分 C API 用法,為 HeadersURLSearchParamsFormDataWorkerEventTarget 新增偵錯器美化列印器,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4187
#4208實作 BigIntStats,作者:@paperclover,位於 https://github.com/oven-sh/bun/pull/4208
#4206feat: 新增自動關閉 & can-have-content,作者:@bru02,位於 https://github.com/oven-sh/bun/pull/4206
#4213當啟用 --inspect 時新增內嵌來源對應,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4213
#4220修正 #172,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4220
#4221修正影響 sharp & resvg 的當機問題,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4221
#4210將不受支援(尚未)註解新增至 distroless 映像檔,作者:@o-az,位於 https://github.com/oven-sh/bun/pull/4210
#4163Fix(bundler): 根據目標使用不同的別名對應。作者:@Hanaasagi,位於 https://github.com/oven-sh/bun/pull/4163
#4231修正來自 3a9a6c63a 的測試失敗問題,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4231
#4222實作 --inspect-brk,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4222
#4230修正 #1675,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4230
#4235修正 buffer.toString("hex") 中的記憶體洩漏問題,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4235
#4237Buffer.toString('hex') 速度提升 40 倍,作者:@Jarred-Sumner,位於 https://github.com/oven-sh/bun/pull/4237
#4243feat: 實作 Bun.inspect.custom,作者:@paperclover
#4156實作 napi_ref_threadsafe_function,作者:@paperclover
#4242修正 crypto.EC 建構函式,作者:@paperclover
#4226Fix(bundler): 允許在巢狀路徑中產生 exe 檔案。作者:@Hanaasagi
#4245修正使用退格鍵 + 引號的 emitKeyPresses 問題,作者:@paperclover
#4127fetch(stream) 為壓縮和未壓縮資料新增串流支援,作者:@cirospaciari
#4244匯入錯誤的 code 設定為 ERR_MODULE_NOT_FOUND,且 require 錯誤的 code 設定為 MODULE_NOT_FOUND,作者:@Jarred-Sumner
#4250修正 stdin 串流 unref 和恢復問題,作者:@dylan-conway
#4247修正 fsevents 和 qwikcity 的 Stub,作者:@paperclover
#4264fix(parser): ] 之前的 yield 不應是語法錯誤,作者:@paperclover
#4256在 PR 範本中要求 bun --revision 而不是 bun -v,作者:@xHyroM
#4273修正更多類型。作者:@xxxhussein
#4251大量串流修正,作者:@Jarred-Sumner

檢視完整變更記錄