Bun v1.1.25 版本在此!此版本修正了 42 個錯誤(解決了 470 個 👍)。支援 node:cluster
和 V8 的 C++ API。Windows 上使用 OMGJIT 加快 WebAssembly 速度。使用 @aws-sdk/client-s3 上傳 S3 速度提升 5 倍、獨立可執行檔中的 Worker,以及更多 Node.js 相容性改進和錯誤修正。
我們正在舊金山招聘系統工程師,共同打造 JavaScript 的未來!
安裝 Bun
curl -fsSL https://bun.dev.org.tw/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
升級 Bun
bun upgrade
node:cluster
支援
Bun 現在支援 node:cluster
API。
這讓您可以執行 Bun worker 池,這些 worker 共用同一個埠,從而在具有多核心 CPU 的機器上實現更高的輸送量和利用率。這非常適合生產環境中的負載平衡。
在 Bun 的下一個版本中
— Bun (@bunjavascript) 2024 年 8 月 18 日
初步的 node:cluster 支援已上線。這是 TypeScript 中每秒 129 萬個 HTTP 請求。pic.twitter.com/YzU1cZxk3S
以下是如何運作的範例
- 主要 worker 產生
n
個子 worker(通常等於 CPU 核心數) - 每個子 worker 監聽同一個埠(使用
reusePort
) - 傳入的 HTTP 請求會在子 worker 之間進行負載平衡
import cluster from "node:cluster";
import http from "node:http";
import { cpus } from "node:os";
import process from "node:process";
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Start N workers for the number of CPUs
for (let i = 0; i < cpus().length; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} exited`);
});
} else {
// Incoming requests are handled by the pool of workers
// instead of the primary worker.
http
.createServer((req, res) => {
res.writeHead(200);
res.end("hello world\n");
})
.listen(3000);
console.log(`Worker ${process.pid} started`);
}
這適用於 node:http
API,以及 Bun.serve()
API。
import cluster from "node:cluster";
import { cpus } from "node:os";
if (cluster.isPrimary) {
for (let i = 0; i < cpus().length; i++) {
cluster.fork();
}
} else {
Bun.serve({
port: 3000,
fetch(request) {
return new Response(`Hello from Worker ${process.pid}`);
},
});
}
請注意,目前 reusePort
僅在 Linux 上有效。在 Windows 和 macOS 上,作業系統不會像預期的那樣對 HTTP 連線進行負載平衡。
感謝 @nektro 實作此功能!
初步的 V8 C++ API 支援
Bun 現在支援 V8 的公開 C++ API,這解鎖了 cpu-features
等套件在 Bun 中運作。
這是一個值得注意的變更,因為 Bun 不是像 Node.js 那樣基於 V8 建構的。相反,Bun 是基於 JavaScriptCore 建構的,JavaScriptCore 是 Safari 瀏覽器使用的 JavaScript 引擎。
這表示我們必須在 V8 的 API 和 JavaScriptCore 之間實作我們自己的 C++ 翻譯層。
#include "v8.h"
#include "V8Primitive.h"
#include "V8MaybeLocal.h"
#include "V8Isolate.h"
namespace v8 {
enum class NewStringType { /* ... */ };
class String : Primitive {
public:
enum WriteOptions { /* ... */ };
BUN_EXPORT static MaybeLocal<String> NewFromUtf8(Isolate* isolate, char const* data, NewStringType type, int length = -1);
BUN_EXPORT int WriteUtf8(Isolate* isolate, char* buffer, int length = -1, int* nchars_ref = nullptr, int options = NO_OPTIONS) const;
BUN_EXPORT int Length() const;
JSC::JSString* localToJSString()
{
return localToObjectPointer<JSC::JSString>();
}
};
}
這是困難的工程工作。JavaScriptCore 和 V8 以不同的方式表示 JavaScript 值。V8 使用移動式並行垃圾收集器和顯式 handle scopes,而 JavaScriptCore 使用非移動式並行垃圾收集器,該收集器掃描堆疊記憶體(有點像隱式 handle scope)。
以前,如果您嘗試匯入使用這些 API 的套件,您會收到類似這樣的錯誤
console.log(require("cpu-features")());
dyld[94465]: missing symbol called
fish: Job 1, 'bun index.ts' terminated by signal SIGABRT (Abort)
現在,cpu-features
等套件可以匯入並在 Bun 中正常運作。
$ bun index.ts
{
arch: "aarch64",
flags: {
fp: true,
asimd: true,
// ...
},
}
這只是支援 V8 內部 API 的開始。如果您的套件遇到我們尚未實作的 V8 API 區域,您會收到一個錯誤,引導您在 GitHub 上為問題投票。
為什麼要支援 V8 的內部 API?
我們最初不打算支援這些 API,但在發現許多熱門套件依賴這些 API 後,我們決定支援,例如
在此版本中,上述列表中僅支援 cpu-features
,但我們正在努力改進支援,以便所有這些套件以及更多套件都能在 Bun 中正常運作。
感謝 @190n 實作此功能!
使用 @aws-sdk/client-s3 將 S3 上傳速度提升 5 倍
我們修正了 node:http client 實作中的一個錯誤,該錯誤使 S3 上傳速度提高了 5 倍。
在 Bun 的下一個版本中
— Ciro Spaciari (@cirospaciari) 2024 年 8 月 21 日
透過 @aws-sdk/client-s3 上傳檔案的速度提升了 5 倍 pic.twitter.com/tptxegT7vh
獨立可執行檔中的 Worker
Bun 的單檔案獨立可執行檔現在支援捆綁 Worker
和 node:worker_threads
。
console.log("Hello from main thread!");
new Worker("./my-worker.ts");
console.log("Hello from another thread!");
若要編譯具有 worker 的獨立可執行檔,請將進入點傳遞給 bun build --compile
bun build --compile ./main.ts ./my-worker.ts
這會將 my-worker.ts
和 main.ts
作為單獨的進入點捆綁到產生的可執行檔中。
在獨立可執行檔中嵌入檔案,無需匯入
現在,如果您願意,可以在獨立可執行檔中嵌入檔案,而無需顯式的 import
語句。
bun build --compile ./main.ts ./public/**/*.png
通常,您必須匯入檔案才能使用它
import logo from "./public/icons/logo.png" with {type: "file"};
但是,有時您想要匯入大量可能需要以程式方式引用的檔案。
Bun.embeddedFiles
新的 Bun.embeddedFiles
API 可讓您查看獨立可執行檔中所有嵌入檔案的清單。
import { embeddedFiles } from "bun";
for (const file of embeddedFiles) {
console.log(file.name); // "logo.png"
console.log(file.size); // 1234
console.log(await file.bytes()); // Uint8Array(1234) [...]
}
這會將所有非 JavaScript 進入點和資源合併到按名稱排序的單個 Blob
物件陣列中。
獨立可執行檔中嵌入檔案的相對匯入
您現在可以使用獨立可執行檔中的相對路徑,參考嵌入檔案的執行階段已知匯入。
function getWasmFilePath(file: string) {
return require.resolve(`./${file}.wasm`);
}
const wasmFile = getWasmFilePath("my-wasm-file");
console.log(wasmFile); // "./my-wasm-file.wasm"
以前,這僅支援在建置時已知的靜態可分析匯入。現在,您可以對任何嵌入檔案執行此操作。
Windows 上使用 OMGJIT 加快 WebAssembly 速度
Windows 上的 WebAssembly 現在支援 JavaScriptCore 的最佳化即時編譯器 (JIT),稱為 OMGJIT。
在 Bun 的下一個版本中
— Bun (@bunjavascript) 2024 年 8 月 17 日
JavaScriptCore 的最佳化 WebAssembly JIT "OMGJIT" 已在 Windows 上啟用,使此 wasm 雜湊基準測試速度提高了 20% pic.twitter.com/8qhKVS4E6z
感謝 Ian Grunert 在 WebKit 中發布此功能!
Node.js 相容性改進
execa
現在可以運作了
我們修正了一個錯誤,Bun 未正確支援 EventTarget
的 setMaxListeners()
。這影響了 execa
等套件,這些套件會因 undefined is not a function
而出錯。
import { execa } from "execa";
const { stdout } = await execa`echo "test"`;
如果您遇到看起來像這樣的錯誤,現在已修正
91 | const controller = new AbortController();
92 | setMaxListeners(Number.POSITIVE_INFINITY, controller.signal);
^
TypeError: undefined is not a function
at node:events:101:30
at spawnSubprocessAsync (/node_modules/execa/lib/methods/main-async.js:92:2)
at execaCoreAsync (/node_modules/execa/lib/methods/main-async.js:26:32)
at index.mjs:3:26
已修正:在 destroy()
之後,node:net
的連線掛起
我們修正了一個錯誤,在 TCP 連線上呼叫 destroy()
並非總是能正確退出程序,因為事件迴圈仍然處於活動狀態。這有時會導致 postgres
等套件無限期掛起。
import net from "node:net";
const server = net.createServer((socket) => {
socket.on("connect", (data) => {
socket.destroy();
// This would destroy the connection,
// but the event loop would still be active
});
});
server.listen(3000);
已修正:node:net.Socket 的 ref 和 unref this
node:net.Socket
上的 ref
和 unref
方法未傳回 this
值。
現在,它們會傳回 this
。
感謝 @nektro 修正此錯誤!
錯誤修正
已修正:TextEncoderStream
產生了錯誤的類型
在 Bun v1.1.23 中,我們引入了對 TextEncoderStream
API 的支援。我們修正了一個錯誤,其中來自串流的區塊是 Buffer
物件而不是 Uint8Array
物件。
const response = await fetch("https://example.com");
const body = response.body.pipeThrough(new TextEncoderStream());
for await (const chunk of body) {
console.log(chunk);
// Before: Buffer
// Now: Uint8Array
}
已修正:Bun shell 中使用跳脫字元反引號時崩潰
我們修正了 Bun shell 中的一個崩潰問題,該問題無法正確處理跳脫字元反引號。
import { $ } from "bun";
console.log(await $`cd \`find -name dir\``.text());
感謝 @zackradisic 修正此錯誤!
已修正:TextEncoder
的 JIT 崩潰
我們修正了一個錯誤,如果 TextEncoder
在執行數百萬次後進行 JIT 編譯,則會崩潰。這是由於 Bun 為在函數上啟用 JIT 而產生的程式碼中的錯誤所致。
已修正:jest.fn 和 mock() 中的崩潰
已修正當使用意外的 this
值在 jest.fn
或 mock()
物件上呼叫函數時可能發生的崩潰。
已修正:IPC 中的崩潰
當子程序在父程序收到訊息之前退出時,在某些情況下可能會發生崩潰。
這已修正,感謝 @cirospaciari。
已修正:console.log 檔案的名稱
當您使用 web File
建構函式建立 Blob 時,檔案名稱未包含在 console.log
的輸出中。
輸入
console.log(new File(["hello world"], "hello.txt"));
新的
File (11 bytes) {
name: "hello.txt",
lastModified: 1724218333315
}
先前
Blob (11 bytes)
已修正:websocket 伺服器中罕見的崩潰
已修正一個罕見的崩潰問題,該問題可能在伺服器呼叫回呼後經過很長時間,並且 ServerWebSocket
物件已被垃圾回收時發生。