Bun v0.5.8 引入了 bun test
中的 expect()
快照(snapshot)測試、使用 bun --preload
預先載入模組、Web API 和 Node.js 相容性的改進、大量的錯誤修正,以及對未來發展方向的預告。
curl -fsSL https://bun.dev.org.tw/install | bash
npm install -g 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
我們正在招募 C/C++ 和 Zig 工程師,一同打造 JavaScript 的未來!
使用 bun test
進行快照測試
bun test
旨在成為高效能、可直接替換 Jest 的工具。現在它支援快照測試,使用 expect(value).toMatchSnapshot()
,它支援與 Jest 相同的快照格式。以下是其運作方式
首先,建立一個測試。
import { test, expect } from "bun:test"; // "bun:test" imports are optional
test("can test a snapshot", async () => {
const response = await fetch("https://example.com/");
const body = await response.text();
expect(body).toMatchSnapshot();
});
然後,使用 bun test
執行測試檔案。
bun test snapshot.test.ts
接著,您將在終端機中看到以下輸出。
snapshot.test.ts:
✓ can test a snapshot
1 pass
0 fail
snapshots: +1 added
1 expect() calls
Ran 1 tests across 1 files [48.00ms]
最後,您會看到已產生新的快照檔案。Bun 使用與 Jest 相同的快照格式,這表示從 Jest 遷移到 bun test
時,您不需要重新產生快照。
exports[`can test a snapshot 1`] = `
"<!doctype html>
<html>
<head>
<title>Example Domain</title>
</head>
</html>
"
`;
如果您需要更新快照,您可以傳遞 --update-snapshots
旗標,這將更新每個已執行測試檔案的快照。
bun test --update-snapshots
除了 toMatchSnapshot()
之外,Bun 現在還支援以下新的匹配器
toThrow(RegExp)
(除了toThrow(string|Error)
之外)toBeInstanceOf()
(感謝 @zhiyuang)toMatch()
(感謝 @zhiyuang)
我們還新增了一個旗標,可以多次重新執行測試檔案,以協助重現不穩定的測試中的錯誤。
bun test --rerun-each=5
這會重新執行每個測試檔案 5 次。
bun --preload <preload> [command]
Bun 現在可以在執行檔案或測試套件之前預先載入檔案。此行為類似於 node --require
。
若要透過 --preload
旗標預先載入檔案
bun --preload ./preload.ts run ./index.ts
若要在 bunfig.toml
中設定要 preload
的檔案清單
preload = ["./preload.ts"]
這對於註冊 plugins
、注入全域變數或執行設定任務非常有用,而無需在您的腳本或進入點中加入額外的 import()
或 require()
陳述式。
以下範例說明如何預先載入 Bun.plugin()
以載入 .yml
檔案。
import config from "./config.yml";
console.log(config);
enabled: true
import { plugin } from "bun";
plugin({
name: "YAML",
async setup(build) {
const { load } = await import("js-yaml");
const { readFileSync } = await import("fs");
// when a .yaml file is imported...
build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
// read and parse the file
const text = readFileSync(args.path, "utf8");
const exports = load(text) as Record<string, any>;
// and returns it as a module
return {
exports: {default: exports, ...exports},
loader: "object", // special loader for JS objects
};
});
},
});
您現在可以從您的進入點匯入 .yml
檔案
bun --preload ./yaml.plugin.ts index.ts
{
enabled: true
}
若要避免使用 --preload
旗標,請設定 bunfig.toml
preload = ["./yaml.plugin.ts"]
現在執行 bun test
或 bun run
將自動預先載入外掛程式。
bun run index.ts
{
enabled: true
}
bun install
workspaces
中的部分 glob 支援
現在 bun install
的 "workspaces"
中支援以下模式
{
"name": "myWorkspace",
"workspaces": [
// Make all folders with a package.json and a name in packages/ part of the workspace
"packages/*"
]
}
您可以使用 /*
將所有符合前綴的資料夾新增到您的工作區。這對於具有許多套件的 monorepo 非常有用。
目前,僅支援在結尾的單一 glob 模式 (foo/*
)。我們計劃在未來改進我們的 glob 支援。同時,當 glob 模式尚未實作時,我們也新增了更佳的錯誤訊息。
Web 相容性
由於 Bun 的測試覆蓋率有所提高,我們修復了 Bun 的 Web API 相容性中的許多錯誤。
request.bodyUsed
& response.bodyUsed
當使用 null
或 undefined
body 時,request.bodyUsed
和 response.bodyUsed
與規範不一致。
const response = new Response(null);
await response.arrayBuffer();
console.log(response.bodyUsed);
/*
Incorrect:
Bun v0.5.7: true
Correct:
Bun v0.5.8: false
Chrome: false
Safari: false
*/
取用 Request
和 Response
的 body
現在可以多次取用 null
或 undefined
的 Request
和 Response
body,這與 Chrome 和 Safari 的行為一致。
先前,當嘗試兩次取用 null
或 undefined
body 時,Bun 會拋出錯誤
bun-0.5.7 response.js
1 | const response = new Response(null);
2 | await response.arrayBuffer();
3 | console.log(await response.arrayBuffer());
^
error: Body already used
現在,null
或 undefined
body 上的 .arrayBuffer()
會改為傳回空的 ArrayBuffer
bun response.js
ArrayBuffer(0) [ ]
/*
Incorrect:
Bun v0.5.7: <error> "Body already used"
Correct:
Bun v0.5.8: ArrayBuffer(0) [ ]
Chrome: ArrayBuffer(0) [ ]
Safari: ArrayBuffer(0) [ ]
*/
同樣地,當沒有 body 時,Response.prototype.body
應該傳回 null
,但 Bun 卻傳回空的 ReadableStream
。
const response = new Response(null);
console.log(response.body);
/*
Incorrect:
Bun v0.5.7: ReadableStream { ... }
Correct:
Bun v0.5.8: null
Chrome: null
Safari: null
*/
blob.slice()
contentType
引數
blob.slice
接受選用的第三個引數,用於新 Blob
的 type
。先前,Bun 不支援此引數。
const blob = new Blob(["Hello, world!"], { type: "text/plain" });
const slice = blob.slice(0, 5, "text/html; charset=utf-8");
console.log(slice.type); // "text/html; charset=utf-8"
/*
Incorrect:
Bun v0.5.7: ""
Correct:
Bun v0.5.8: "text/html; charset=utf-8"
Chrome: "text/html; charset=utf-8"
Safari: "text/html; charset=utf-8"
*/
Request
建構子
Bun 中的 Request
建構子有一些錯誤。
當給定兩個引數時,它總是預期第一個引數是字串,這是錯誤的。
// This didn't work: (inconsistent with the spec)
new Request(new Request("https://example.com"), {});
// But any of these did:
new Request(new Request("https://example.com"));
new Request("https://example.com", { method: "POST" });
new Request("https://example.com", {});
這已修正,現在第一個引數可以是字串或 Request
物件。
// This works now:
console.log(new Request(new Request("https://example.com"), {}).url);
// "https://example.com"
另一個錯誤:url
引數未正確驗證(在 fetch()
中驗證,但在 new Request()
中未驗證)
// this is supposed to throw:
const request = new Request("", { method: "POST" });
現在它(正確地)拋出錯誤
bun /tmp/app.js
1 | const request = new Request("", { method: "POST" });
^
error: Failed to construct 'Request': url is required.
Bun 對於 Request
建構子的測試覆蓋率不足,且 Bun 的 fetch
實作(確實會驗證)未使用與 Request
建構子相同的程式碼路徑。
Node.js 相容性
Bun 持續改進 Node.js 相容性。以下是自上次發佈以來變更的內容。
- 大幅改進了
Buffer
實作,現在通過了更多 Node.js 測試 - 針對 macOS 實作了
os.cpus()
(先前僅在 Linux 上支援) - 實作了
os.networkInterfaces()
- 新增了
AbortSignal
對http.Server
和http.ClientRequest
的支援 node:net
的伺服器函數listen
回呼現在在伺服器正在監聽後觸發,而不是有時在伺服器正在監聽之前觸發node:zlib
缺少constants
的匯出
Bun.sleepSync()
為了修正 Bun.sleep()
和 Bun.sleepSync()
之間的不一致問題,有一個重大變更,Bun.sleepSync()
現在接受毫秒,而不是秒。透過在 GitHub 上使用程式碼搜尋,我們發現大多數用法已經假設單位是毫秒。
Bun.sleepSync(1); // sleep for 1 ms (not recommended)
await Bun.sleep(1); // sleep for 1 ms (recommended)
接下來是什麼?
對於 Bun v0.6,您可以期待重大的變更,包括全新的打包器!
比 webpack 更小的 bundle 大小(在縮小化之後)pic.twitter.com/OptyA2TSCY
— Jarred Sumner (@jarredsumner) 2023 年 3 月 17 日
Bun 即將推出的打包器旨在讓建置現代化的全堆疊 JavaScript 和 TypeScript 應用程式更簡單(且更快速)。
當然,隨著 Bun 逐漸接近 1.0 版本,我們將繼續朝著 Node.js 相容性、整體穩定性和效能的優先事項邁進。為了衡量朝著這些目標的進展,我們大幅提高了 Bun、Node.js 和標準 Web API 的測試覆蓋率。敬請期待。
變更記錄
#2156 | 修正了 {Request,Response}.body 不為 null 的問題,由 @cirospaciari 貢獻 |
#2115 | 針對 macOS 實作了 os.cpus() ,由 @jwhear 貢獻 |
#2161 | 修正了 HTMLRewriter.onDocument() 未執行的問題,由 @jwhear 貢獻 |
#2144 | 修正了 dns.{resolve4,resolve6}() 的傳回值不正確的問題,由 @cirospaciari 貢獻 |
599f63c | 支援舊版 macOS,包括 10.15,由 @Jarred-Sumner 貢獻 |
0a7309c | 改進了 EventEmitter 的效能,由 @Jarred-Sumner 貢獻 |
eb94e5b | 將 BoringSSL 變更為從 mimalloc 使用 heap,由 @Jarred-Sumner 貢獻 |
#2192 | 改進了 bun pm ls 的穩定性,由 @alexlamsl 貢獻 |
693be3d | 改進了 ASCII 不區分大小寫比較的效能,由 @Jarred-Sumner 貢獻 |
#2202 | 修正了 ANSI escape codes 未從 stdout 管道傳輸到檔案的問題,由 @alexlamsl 貢獻 |
5d296f6 | 修正了 shasum 被剖析兩次的問題,由 @Jarred-Sumner 貢獻 |
#2213 | 修正了 bun install 和重複依賴項的問題,由 @alexlamsl 貢獻 |
#2142 | 實作了 os.networkInterfaces() ,由 @jwhear 貢獻 |
#2191 | 修正了 bun dev 的埠號不正確的問題,由 @xjmdoo 貢獻 |
#2143 | 修正了關閉時 fetch({ signal }) 的問題,由 @cirospaciari 貢獻 |
#2223 | 實作了 http.listen({ signal }) ,由 @cirospaciari 貢獻 |
#2222 | 實作了 http.get({ signal }) ,由 @cirospaciari 貢獻 |
#2226 | 移除了 sqlite 在給定空陳述式時的暫時性錯誤,由 @ThatOneBro 貢獻 |
#2231 | 實作了 bun --preload <file> ,由 @Jarred-Sumner 貢獻 |
#2249 | 修正了空檔案上 Bun.file().arrayBuffer() 的問題,由 @cirospaciari 貢獻 |
#2258 | 修正了 http.request() 不接受 URL 的錯誤,由 @ThatOneBro 貢獻 |
#2262 | 改進了當 method 為 GET 或 HEAD 且具有 body 時 http.request() 的相容性,由 @ThatOneBro 貢獻 |
#2242 | [重大變更] Bun.sleepSync() 現在以毫秒為單位,而不是秒,由 @jwhear 貢獻 |
#2276 | 修正了 os.tmpdir() 從移除尾部斜線的問題,由 @cirospaciari 貢獻 |
#2285 | 修正了 node:http 中 request.url 不包含 search params 的問題,由 @zhiyuang 貢獻 |
#2295 | 變更了不帶參數的 bunx 以顯示說明頁面,由 @Zeko369 貢獻 |
#2288 | 修正了 node:http 中標頭未小寫的問題,由 @ThatOneBro 貢獻 |
#2293 | 修正了 bunx 無法找到 scoped npm 套件的問題,由 @Zeko369 貢獻 |
#2302 | 修正了在 semver 範圍內未考量 "latest" 的問題,由 @alexlamsl 貢獻 |
#2307 | 修正了 bun install 未向 npm 登錄檔報告連線錯誤的問題,由 @alexlamsl 貢獻 |
#2314 | 實作了 expect().toThrow(RegExp) ,由 @alexlamsl 貢獻 |
#2315 | 修正了 Linux 上 Blob 的錯誤訊息,由 @alexlamsl 貢獻 |
#2320 | 為 process.{stdout,stderr} 實作了部分 tty.WriteStream ,由 @ThatOneBro 貢獻 |
0a9cb0e | 修正了 HTMLRewriter 收到空字串時的問題,由 @Jarred-Sumner 貢獻 |
#2331 | 修正了 crypto.scryptSync() 的參數錯誤,由 @dylan-conway 貢獻 |
#2341 | 改進了 Buffer 與 Node.js 的相容性,由 @alexlamsl 貢獻 |
e16053c | 修正了 crypto.createHash().update("binary") 無法運作的問題,由 @Jarred-Sumner 貢獻 |
#2340 | 改進了 Blob.type 的規格相符性,由 @Jarred-Sumner 貢獻 |
#2371 | 修正了當 require.resolve() 引數為空時的錯誤,由 @paperclover 貢獻 |
#2337 | 在 net.Server 中實作了 unix socket 支援,由 @cirospaciari 貢獻 |
4c38798 | 修正了 Socket.remoteAddress 的編碼不正確的問題,由 @Jarred-Sumner 貢獻 |
27f5012 | 修正了 node:https 為唯讀的問題,由 @Jarred-Sumner 貢獻 |
#2389 | 實作了 expect().toBeInstanceOf() ,由 @zhiyuang 貢獻 |
e613b50 | 在 node:zlib 中實作了遺失的 constants ,由 @Jarred-Sumner 貢獻 |
#2294 | 實作了 expect().toMatchSnapshot() ,由 @dylan-conway 貢獻 |
#2397 | 修正了剖析格式錯誤的 bun.lockb 的問題,由 @alexlamsl 貢獻 |
#2400 | 修正了 Bun.serve() 無法在 IPv6 上監聽的問題,由 @cirospaciari 貢獻 |
9a5f78f | 修正了 console.log() 未顯示 [Getter] 值的问题,由 @Jarred-Sumner 貢獻 |
#2404 | 實作了 expect().toMatch(RegExp) ,由 @zhiyuang 貢獻 |
此外,如果您還沒聽說,Bun 現在有文件了!
非常感謝 @colinhacks,以及自上次發佈以來做出貢獻的許多人:@jakeboone02、@charliermarsh、@BrettBlox、@damianstasik、@Sheraff、@johnnyreilly、@fdaciuk、@akash-joshi、@TommasoAmici、@raxityo、@DreierF、@rmorey、@cunzaizhuyi、@rodoabad、@gaurishhs、@maor-benami、@aabccd021、@pfgithub、@bushuai、@Zeko369、@noahmarro、@harisvsulaiman、@nskins、@milesj 和 @jsoref。