我們正在招募 C/C++ 和 Zig 工程師,一同打造 JavaScript 的未來! 加入我們的團隊 →
我們最近發布了許多 Bun 的變更,這裡為您整理摘要,以防您錯過任何資訊
v0.6.0
- 推出bun build
,Bun 的全新 JavaScript 打包器。v0.6.2
- 效能提升:JSON.parse
速度提升 20%,Proxy
和arguments
速度提升高達 2 倍。v0.6.3
- 實作node:vm
,並對node:http
和node:tls
進行了許多修正。v0.6.4
- 實作require.cache
、process.env.TZ
,以及bun test
速度提升 80%。v0.6.5
- 原生支援 CommonJS 模組 (先前,Bun 會將 CJS 轉譯為 ESM),v0.6.6
-bun test
改進,包括 Github Actions 支援、test.only()
、test.if()
、describe.skip()
,以及 15 個以上的expect()
匹配器;也支援使用fetch()
串流檔案上傳。v0.6.7
- Node.js 相容性改進,以解除對 Discord.js、Prisma 和 Puppeteer 的封鎖v0.6.8
- 推出Bun.password
、bun test
中的模擬功能,以及toMatchObject()
v0.6.9
- 減少記憶體用量並支援非 ASCII 檔案名稱
安裝 Bun
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
改進的 CommonJS 支援
現在在 Bun 中載入 npm 套件更加可靠。這是因為我們(再次)重寫了 CommonJS 模組載入。我們修正了許多與載入 CommonJS 模組相關的崩潰問題,並改進了 CommonJS 模組載入器,使其更相容於 Node.js。
webpack
現在可在 Bun 中運作
在 Bun 的下個版本中
— Jarred Sumner (@jarredsumner) 2023 年 6 月 26 日
webpack 似乎可以運作了,感謝 @dylanconway111 和 @cirospaciari pic.twitter.com/V9HEl3YRXy
require.main
現在受到支援
require.main
是 Node.js CLI 常用的方法,用於檢查目前執行的腳本是否啟動了進程
if (require.main === module.id) {
// do something
}
Bun 現在支援 require.main
,這解鎖了多個 Node.js CLI。
我們也新增了 process.mainModule
,它是 require.main
的別名。
console.log(require.main === process.mainModule); // true
__esModule
註解現在受到支援
Bun 現在具有執行階段支援,可支援 bundler 和 TypeScript 使用的 __esModule
註解,以指示當將 CommonJS 模組作為 ES 模組匯入時,default
匯出應指向的內容。
__esModule
是一種註解,用於保留轉換為 CommonJS 並隨後重新匯入回 ESM 的 ESM 的 export default <value>
。
import a from 'b'
應參照 module.exports
還是 module.exports.default
?
這個問題是讓 JavaScript 生態系統的 CommonJS -> ES 模組轉換變得困難的原因之一。
__esModule
是一種保留 default
匯入的方法,該匯入由 Webpack、Babel、esbuild 產生,並在 npm 上的許多套件中使用。Bun 現在具有對此的執行階段支援。
這表示以下的輸入 ES 模組
export default 42;
通常會由建置工具轉換為發布到 npm 的 CommonJS,如下所示
exports.default = 42;
exports.__esModule = true;
當重新匯入回 ESM 時,__esModule
註解會保留 default
值
import foo from "./foo.js";
console.log(foo); // 42
請注意,在 Node.js 中,default
匯出不會保留
import foo from "./foo.js";
// This is already the "default" export
// so why should you have to do .default to get the original value?
console.log(foo.default); // 42
為了繼續與 Node.js 相容,當沒有 __esModule
註解或封閉的 package.json 將 "type"
設定為 "module"
時,此行為會停用(表示這用於 Node.js 通常無論如何都不支援 ESM 的情況)。
WebSocket 客戶端編碼修正
我們修正了 Bun 的 WebSocket
客戶端實作中的一個編碼錯誤,該錯誤可能導致 Latin1 編碼的文字框架被截斷。
由於這些變更,Bun 中 puppeteer
的支援已獲得改進。
import puppeteer from "puppeteer";
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://example.com/");
await page.click("a");
await browser.close();
bun:test
的改進
現在使用 bun test
時,Bun 支援更多匹配器
import { test, expect } from "bun:test";
test("new matchers", () => {
expect(fetch("http://example.com")).resolves.toBeInstanceOf(Response);
expect(fetch("invalid")).rejects.toBeInstanceOf(Error);
expect([]).toBeArray();
expect([1, 2, 3]).toBeArrayOfSize(3);
expect("").toBeTypeOf("string");
});
spyOn()
的模擬支援也得到了改進。
import { test, expect, spyOn } from "bun:test";
test("spyOn()", () => {
const service = {
hasPermission: () => false,
};
let hasPermission = false;
const spy = spyOn(service, "hasPermission").mockImplementation(
() => hasPermission,
);
hasPermission = true;
expect(service.hasPermission()).toBe(true);
expect(spy).toHaveBeenCalled();
});
有了所有這些變更,將您現有的專案遷移到使用 bun test
應該比以往任何時候都更快更容易。以下是一個熱門 npm 套件(例如 zod
)遷移到 bun test
時的情況。
針對 Zod 的測試套件,Bun / Vitest / Jest 的效能基準測試
— Colin McDonnell (@colinhacks) 2023 年 6 月 26 日
Bun — 230 毫秒
Vitest — 1.9 秒 (慢 8 倍)
Jest + SWC — 3 秒 (慢 13 倍)
Jest w/ ts-jest — 6.7 秒 (慢 29 倍)
Jest w/ Babel — 7.4 秒 (慢 32 倍) pic.twitter.com/RFqZ06hH5K
.env
支援的錯誤修正
Bun 內建支援將 .env
檔案載入到 process.env
中,讓您無需在啟動時執行 require("dotenv").config()
,並允許您在測試和 package.json "scripts"
中使用 .env
檔案。
此功能存在一些錯誤,@alexlamsl 已將其修正
- Windows 樣式的新行可能會導致其崩潰 https://github.com/oven-sh/bun/issues/411
- 當
.env
中環境變數的值內有$
時,會被視為巢狀變數,但不應該如此 https://github.com/oven-sh/bun/issues/2823 - 特定長度的輸入會導致崩潰 https://github.com/oven-sh/bun/issues/3042
Node.js 相容性改進
在 Bun 中監看檔案
fs.watch()
現在已實作!
import { watch } from "node:fs";
// file path
watch(".", (eventType, filename) => {
console.log(`event type = ${eventType}`);
if (filename) {
console.log(`filename = ${filename}`);
}
});
Bun.argv
現在與process.argv
相符。
import { deepEquals } from "bun";
console.log(deepEquals(Bun.argv, process.argv)); // true
- 現在可以使用更多 V8 的 堆疊追蹤 API。
function getStack() {
const cause = new Error();
const prevPrepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = (_, stack) => {
console.log(stack[0].getFunctionName()); // "getStack"
console.log(typeof stack[0].getLineNumber()); // "number"
console.log(typeof stack[0].getColumnNumber()); // "number"
};
Error.captureStackTrace(cause);
Error.prepareStackTrace = prevPrepareStackTrace;
}
import { openSync, writevSync } from "node:fs";
const fd = openSync("path/to/file");
const buffers = [new Uint8Array(3), new Uint8Array(3), new Uint8Array(3)];
console.log(writevSync(fd, buffers)); // 9
- 現在支援
Module._nodeModulePaths
。此函數會傳回 Bun 將在其中搜尋模組的路徑陣列。
import { _nodeModulePaths } from "node:module";
console.log(_nodeModulePaths(".")); // ["/path/to/node_modules", "/path/node_modules", "/node_modules"]
- 現在支援
crypto.randomInt()
,感謝 @lenovouser util.deprecate
現在支援"code"
引數fs.createWriteStream
現在可以正確傳遞 flags,感謝 @Hanaasagi
bun install
的改進
我們也對 bun install
進行了一些新增功能。
--exact <package>
bun install --exact
提供與 npm install --save-exact
或 yarn add --exact
相同的行為。它會將您正在安裝的套件版本固定為您指定的確切版本。
bun install --exact elysia@0.5.20
--frozen-lockfile
在此模式下,如果 bun.lock
檔案與 package.json
不同步,Bun 將會拋出錯誤。這對於 CI 環境很有用,您可以在 CI 環境中確保 bun.lock
是最新的。
bun install --frozen-lockfile
trustedDependencies
現在您可以設定允許執行生命週期腳本(例如 postinstall
)的依賴項允許清單。預設情況下,這些腳本不會執行,以使 Bun 在預設情況下更安全。
{
"trustedDependencies": [
"puppeteer"
]
}
我們計劃在不久的將來新增一個預設清單,以便預設情況下,安裝依賴 postinstall 的套件能夠如預期般運作。
更多錯誤修正
- 已修正使用
Bun.write
寫入檔案時可能發生的崩潰 node:tls
模組缺少一些 ES 匯出bun:sqlite
套件缺少Database
類別的default
匯出mkdirSync(path, {recursive: true})
有時會在不應該的情況下傳回空字串- 例外狀況記錄中的檔案名稱有時會損毀,此問題已修正
- 修正了檔案:URL 的模組解析中的錯誤,其中包含空格字元的 URL 會以 % 編碼而不是解碼
- 修正了當 readdir 傳回大型目錄且某些元素為 UTF-16 時發生的崩潰
- 修正了當 node:fs 函數中的布林值引數作為非布林值引數傳遞時可能發生的崩潰
更多新功能
- 現在支援 HTMLRewriter 的
TextChunk
中的lastInTextNode
屬性,它可以告訴您目前的文字區塊是否為最後一個。感謝 @bru02
更新日誌
#3310 | 將 Bun.argv 變更為與 process.argv 相同,由 @Jarred-Sumner 執行 |
7f535a2 | 修正了指派 module.require 時的問題,由 @Jarred-Sumner 執行 |
#3314 | 改進了 Bun.serve 選項的驗證,由 @cirospaciari 執行 |
#3320 | 修正了 CommonJS 匯入的錯誤,由 @Jarred-Sumner 執行 |
#3337 | 修正了 const 宣告可能在使用前被 tree-shaked 的錯誤,由 @dylan-conway 執行 |
8ad9e57 | 新增了 ucs2 編碼的遺失別名,由 @Jarred-Sumner 執行 |
b951c1f | 全面改進了記憶體用量,由 @Jarred-Sumner 執行 |
#3362 | 改進了檔案沒有匯出時對 ESM 和 CommonJS 的偵測,由 @Jarred-Sumner 執行 |
#3316 | 為 bun:test 實作了 toBeArray 、toBeArrayOfSize 和 toBeTypeOf ,由 @TiranexDev 執行 |
#3359 | 實作了更多 V8 的堆疊追蹤 API,由 @kvakil 執行 |
#3363 | 修正了 fs.utimesSync() 的溢位問題,由 @Jarred-Sumner 執行 |
83d7ec7 | 修正了 node:crypto 的 .digest() 後 .copy() 的錯誤,由 @Jarred-Sumner 執行 |
#3367 | 為 toEqual 、toStrictEqual 和 toHaveProperty 實作了非對稱匹配器支援,由 @dylan-conway 執行 |
#3360 | 修正了經典模式中 JSX 的錯誤,由 @dylan-conway 執行 |
#3368 | 改進了循環依賴的錯誤訊息,由 @Jarred-Sumner 執行 |
#3369 | 修正了 .env 檔案的崩潰問題,由 @Jarred-Sumner 執行 |
#3304 | 在 bun:test 中實作了更多 mock() 支援,由 @paperclover 執行 |
#3378 | 修正了 CommonJS 檔案中 bun:test 的使用問題,由 @Jarred-Sumner 執行 |
#3347 | 修正了 .env 檔案剖析的各種錯誤,由 @alexlamsl 執行 |
#3318 | 為 expect() 實作了 resolves 和 rejects ,由 @Electroid 執行 |
#3377 | 修正了 node-fetch 匯入的錯誤,由 @paperclover 執行 |
#3376 | 在 bun:test 中實作了 spyOn() ,由 @paperclover 執行 |
#3249 | 實作了 fs.watch() ,由 @cirospaciari 執行 |
#3379 | 重寫了 CommonJS 的支援,由 @Jarred-Sumner 執行 |
#3394 | 修正了 WebSocket 中 Latin1 字串的錯誤,由 @Jarred-Sumner 執行 |
#3400 | 修正了 bun install --production 可能發生的崩潰,由 @Jarred-Sumner 執行 |
5bd94b8 | 實作了 process.mainModule ,由 @Jarred-Sumner 執行 |
#3402 | 修正了 WriteStream 建構函式的錯誤,由 @Hanaasagi 執行 |
#3405 | 實作了將檔案嵌入已編譯可執行檔的支援,由 @Jarred-Sumner 執行 |
#3365 | 實作了 bun install --frozen-lockfile ,由 @tiagotex 執行 |
#3356 | 更新 lol-html,由 @bru02 執行 |
#3401 | 修正了 lol-html 的崩潰問題,由 @Jarred-Sumner 執行 |
#3411 | 實作了 _nodeModulePaths 和 require.main.paths ,由 @dylan-conway 執行 |
#3288 | 在 package.json 中實作了 trustedDependencies ,由 @alexlamsl 執行 |
#3419 | 實作了 writev 和 readv ,由 @Jarred-Sumner 執行 |
#3393 | 實作了 __esModule 註解,由 @Jarred-Sumner 執行 |