Bun 0.6.4 正式發布,你學會了嗎?
大家好,我是Echa。
好消息,2023年5月26號Bun 官方對外發布 Bun 0.6.4 版本,距離上一次Bun 0.6.0版本(2023年5月16號),短短只有10天時間。據 Bun官方的說法是,Bun 0.6.0 版本是迄今為止 Bun 最大的一次更新版本。接下來小編帶著大家細聊Bun 最近更新了哪些內容。
全文大綱
- Bun 前言
- 全新的Bun 官網介紹
- Bun最新版更新重點
Bun 前言
Bun Github 41.6k
剛開源不到一個月就獲得了 26k多star!現在已經41.6k star。看起來馬上就會成為 Node.js 和 Deno 的一大競爭對手了!和傳統的 Node.js 這種傳統的 javaScript 運行時不同,Bun.js 直接內置了打包器、轉譯器、任務運行器和 npm 客戶端,這意味著你不再需要
Webpack/Rollup/esbuild/Snowpack/Parcel/Rome/swc/babel 就可以直接運行 TypeScript、JSX!
另外,Bun.js 原生支持了數百個 Node.js 和 Web API,包括約 90% 的 Node-API 函數(fs、path、Buffer 等)。
Bun.js 的目標是可以在瀏覽器之外的其他地方運行世界上大多數 JavaScript,為你未來的基礎架構帶來性能和復雜性的增強,并通過更好、更簡單的工具提高開發者的生產力!
在2022 年 JavaScript 明星項目中Bun排名第一
2022 年 JavaScript 明星項目中Bun排名第一
Bun 是 一個專注性能與開發者體驗的全新 JavaScript 運行時。它的流行程度伴隨著在今年夏天發布的第一個 Beta 版而爆炸性增長:僅一個月內,就在 GitHub 上獲得了超過兩萬顆星星。自從我們在 Best of JS 開始統計項目以來,我們還從未見過這樣的爆炸。
那么,是什么讓 Bun 與眾不同呢?與兩年前的總冠軍 Deno 一樣,它也為 TypeScript 提供了一流的支持。
但 Bun 不僅僅是一個運行時。它也是:
- 一個包管理器 (類似 Yarn、 NPM、 PNPM)
- 一個構建工具 (類似 Webpack、 ESBuild、 Parcel)
- 一個測試運行器
- ... 以及很多其他東西!
所以 Bun 可以通過讀取你的 package.json 來安裝依賴項。Bun 還可以運行你的腳本。不管它做什么都比其他工具更快。
Bun 在 JavaScript 生態系統的許多方面都有新的嘗試,其中的重點是性能。
它優先支持標準的 Web API,如 Fetch。它也支持許多 Node.js APIs,使其能與大多數 NPM 包兼容。
它可能還沒到 “能用于生產” 的階段(缺乏 Windows 支持),但它依舊是一個非常有前途的工具。與 Deno 相比,它的生態系統相當新,但它已經有一個名為 Elysia 的網絡框架,其聲稱是最快的 HTTP 框架。
Bun 作者 Jarred Sumner
Bun 最不可思議的是,它的創造者 Jarred Sumner 用的是一種名為 Zig 的低級語言從零開始實現了所有這些功能。
全新的Bun 官網介紹
官網:https://bun.sh/
Github:https://github.com/oven-sh/bun
今天的主角,Bun.js(下稱 Bun),新一代的 All-In-One 的 JavaScript 運行時,Node.js(下稱 Node) 和 Deno 的挑戰者。
Bun是一個全新的JavaScript運行庫,從頭開始構建,為現代JavaScript生態系統服務,有三個主要設計目標:
- 快速啟動。在邊緣計算環境中,減少冷啟動時間至關重要。
- 快速運行性能。Bun擴展了JavaScriptCore,這是為Safari構建的注重性能的JS引擎。
- 粘性DX。Bun是一個用于構建JavaScript應用程序的完整工具包,包括bundler、transpiler和包管理器。
Bun是Node.js的替代品。使用它可以在本地計算機、服務器或邊緣運行當前的JavaScript&TypeScript應用程序或腳本。Bun本機實現了數百個Node.js和Web API,包括約90%的Node-API函數(本機模塊)、fs、path、Buffer等。
Bun的目標是在瀏覽器之外運行世界上大多數的JavaScript,為您未來的基礎設施帶來性能和復雜性增強,并通過更好、更簡單的工具提高開發人員的生產力。
Bun 性能表現如何?
服務端渲染:每秒處理 HTTP 請求數對比
每秒處理 HTTP 請求數對比
每秒發送的郵件數對比:
每秒發送的郵件數對比
加載一個巨大的 sqlite 表:每秒平均查詢次數對比
每秒平均查詢次數對比
Bun bundler簡介
一個快速的JavaScript打包程序。用于web瀏覽器的捆綁、樹搖和迷你ES模塊、CommonJS、TypeScript和JSX。
為啥這么快?
和 Node.js、Deno 不同,Bun.js 并沒有基于 V8 引擎,它直接選擇了 JavaScriptCore 引擎,它的執行速度往往要比 V8 等更傳統引擎要快。
另外,Bun.js 是用一種具有手動內存管理的低級編程語言 ZIG 編寫的,對內存的低級控制、沒有隱藏的控制流可能就是它性能非常好的秘訣。
Bun.js 的大部分內容都是完全從零開始編寫的,包括 JSX/TypeScript 轉譯器、npm 客戶端、打包器、SQLite 客戶端、HTTP 客戶端、WebSocket 客戶端等等。
有哪些能力?
- Web API:對 fetch、WebSocket、 ReadableStream 等 API 都提供了內置支持
- Node.js 模塊:Bun 實現了 Node.js 的模塊解析算法,同時支持 ESM 和 CommonJS,但 Bun 內部使用 ESM。
- 支持轉譯大量文件類型,你可以直接運行 TypeScript、JSX,甚至支持各種 tsconfig.json 中的配置。
Bun最新版更新重點
Bun 0.6.0 版本
根據官方說法,Bun 0.6.0 版本是迄今為止 Bun 最大的一個更新版本。
最新版本的 Bun 現在有一個內置的 JavaScript 和 TypeScript 捆綁器和簡化器,可以用它來捆綁前端應用程序或將你的代碼捆綁成一個獨立的可執行文件。
Bun 0.6.0 也一直在忙著提高性能和修復 bug:writeFile() 在 Linux 上的速度提高了 20%、對 Node.js 兼容性和 Web API 兼容性進行了大量的 bug 修復、支持 TypeScript 5.0 語法,并對 bun install 進行了各種修復。
新的 JavaScript bundler & minifier
這個版本的重點是 Bun 的新 JavaScript Bundler(捆綁器),但捆綁器只是一個更大項目的開始。在接下來的幾個月里,Bun 將發布 Bun.App—— 一個 "超級 API",將 Bun 的 native-speed 捆綁器、HTTP 服務器和文件系統路由縫合成一個整體。
可以使用 bun build CLI 命令或新的 Bun.build() JavaScript API 來使用。
JavaScript
Bun.build({
entrypoints: ["./src/index.tsx"],
outdir: "./build",
minify: true,
// ...
});
CLI
bun build ./src/index.tsx --outdir ./build --minify
獨立的可執行文件
現在你可以用 bun build 來創建獨立的可執行文件。
bun build --compile ./foo.ts
這讓你可以將你的應用程序作為一個可執行文件發布,而不需要用戶安裝 Bun。
你也可以將其縮小,以提高大型應用程序的啟動性能:
bun build --minify --compile ./three.ts
[32ms] minify -123 KB (estimate)
[50ms] bundle 456 modules
[107ms] compile three
這是由 Bun 的新 JavaScript 捆綁器和簡化器提供的。
import.meta.main
現在你可以使用 import.meta.main 來檢查當前文件是否是啟動 Bun 的入口點。這對 CLI 很有用,可以確定當前文件是否是啟動應用程序的。
例如,如果你有一個名為 index.ts 的文件:
index.ts
console.log(import.meta.main);
然后你運行它:
$ bun ./index.ts
true
但如果你導入它:
import "./index.ts";
并運行它:
$ bun ./other.ts
false
對bun test的改進
- bun test 現在報告運行測試的時間
- describe.skip 已經實現
- 實現了 expect().toBeEven() 和 expect().toBeOdd()
在 Linux 上實現更快的fs.writeFile
fs.writeFile 在 Linux 上處理大文件的速度提高了 20%
轉譯器改進
這個版本還引入了許多對轉譯器的改進。以下是其中的一些亮點:
- 解析器支持 TypeScript 5.0。
- 解析器支持導入屬性。
- 一些 npm 包出現了 ReferenceError: Cannot access uninitialized variable 的錯誤,這是由于 Bun 的轉譯器中存在循環導入的錯誤。這一點已被修復。
- 支持 // @jsx、// @jsxImportSource 和 // @jsxFragment 注釋
- ……
Bun Bundler
Bun的快速原生bundler現在處于測試階段。它可以通過bun-build CLI命令或新的bun.build()JavaScript API使用。
使用bundler通過內置Bun.build()函數或Bun-build CLI命令構建前端應用程序。
Bun.build({
entrypoints: ['./src/index.tsx'],
outdir: './build',
minify: true,
// additional config
});
降低JavaScript的復雜性
JavaScript最初是表單字段的自動填充,如今它為向太空發射火箭的儀器提供動力。
不出所料,JavaScript生態系統的復雜性激增。如何運行TypeScript文件?您如何構建/捆綁您的代碼以用于生產?該軟件包適用于ESM嗎?如何加載僅本地配置?我需要安裝對等依賴項嗎?如何使源地圖正常工作?
復雜性需要時間,通常需要將工具粘在一起或等待完成。安裝npm程序包花費的時間太長。運行測試應該需要幾秒鐘(或更短)。為什么在2023年部署軟件需要幾分鐘,而在2003年將文件上傳到FTP服務器需要幾毫秒?
多年來,我一直對JavaScript的速度感到沮喪。當從保存文件到測試更改的迭代周期長到足以本能地檢查Hacker News時,就說明出了問題。
這種復雜性是有充分理由的。捆綁包和迷你包使網站加載更快。TypeScript的編輯器內交互式文檔使開發人員的工作效率更高。類型安全有助于在錯誤發送給用戶之前發現錯誤。作為版本化包的依賴項通常比復制文件更容易維護。
當“一件事”被拆分在這么多孤立的工具之間時,Unix的“做好一件事情”哲學就崩潰了。
toLocaleString()速度提高79倍
多虧了@Constellation,數字上的toLocaleString()速度提高了79倍。
toLocaleString將數字轉換為當前區域設置預期讀取字符串的方式。
這對代碼的影響如下:
const myNumber = 123;
myNumber.toLocaleString();
JSON.parse快20%,JSON.stringify快15%
多虧了@Constellation,在沒有許多嵌套對象的對象上,JSON.parse在對象上的速度快了20%,而在相同的場景中,JSON.stringify的速度快15%。
之前:
之后:
Node.js,用于比較:
Object.assign 用空對象分配會更快
多虧了@Constellation,Object.assign()和空對象作為第二個參數,速度快了2倍。
function test(options) {
var options = Object.assign({ defaultParam: 32 }, options);
return options;
}
// empty object as the 2nd arguemnt to object assign
test({});
返回參數的速度快2倍
也多虧了@Constellation,在函數中返回參數的速度提高了2倍
function test(a, b, c) {
return arguments;
}
for (var i = 0; i < 1e6; ++i) test(0, 1, 2);
涉及模板字符串的小型化程序錯誤
由于bun的解析器中模板文本中包含字符串的邏輯不正確,這樣的代碼有時會產生不正確的字符串:
const foo = ".*";
const regex1 = new RegExp(foo); // Invalid regular expression: unmatched parentheses
const regex2 = new RegExp(`(${foo})`);
Bun 0.6.3 版本
官方我們發布了對node:vm的支持、對node:tls和node:http的改進,修復了對socket.io和mongodb的支持,對bun-test的改進,引入了test.todo()、測試超時和更好的預加載,以及對bun的bundler的許多修復。
介紹節點:vm
Bun現在支持內置的node:vm模塊。它可以用來執行代碼,類似于eval(),只是對代碼執行的globalThis JavaScript上下文有更多的控制。
import { runInContext } from "node:vm";
let context = {
foo: "bar",
baz: 123,
};
runInContext(`foo = "fizz"; delete baz;`, context);
console.log(context.foo); // "fizz"
console.log(context.baz); // undefined
您還可以使用runInNewContext在單獨的JavaScript上下文中運行代碼。
import { runInNewContext } from "node:vm";
runInNewContext(`globalThis.fetch = undefined;`);
console.log(globalThis.fetch); // [Function fetch]
修復了node:tls和node:http
官方我們已經修復了許多使用TLS和HTTP的代碼,例如TLS握手,因此您現在可以在Bun中使用socket.io和mongodb身份驗證。
bun測試的改進
現在,您可以使用test.todo()標記以后要實現的測試。
expect().toBeCloseTo()
import { test, expect } from "bun:test";
test("toBeCloseTo()", () => {
expect(3 + 0.14).toBeCloseTo(3.14);
expect(3.14).toBeCloseTo(Math.PI, 2);
});
Test timeouts
import { test } from "bun:test";
test("i took too long", async () => {
await Bun.sleep(100);
}, 50); // the last argument is a timeout in milliseconds
Hook support with --preload
現在可以使用帶有--preload標志的beforeAll、beforeEach、afterEach和afterAll。
這使您可以在所有文件之前和之后運行代碼,而不僅僅是當前文件。這對于在運行測試之前需要初始化的庫非常有用。
import { test, beforeAll, beforeEach, afterEach, afterAll } from "bun:test";
beforeEach(() => {
console.log("This runs before each test in every file");
});
Fixes to pretty-printing
官方我們還修復了一個錯誤,該錯誤會導致像這樣的代碼在測試運行程序中將值打印為未定義值。
import { test, expect } from "bun:test";
test("wat", () => {
const left = {};
const right = {};
for (let i = 0; i < 2; i++) {
left[i] = i + 1;
right[i] = i + 2;
}
expect(left).toBe(right);
});
Fixes tobun build
- 當啟用了具有多個入口點的--minify時,在使用Bun.js作為捆綁程序時突出顯示的崩潰已修復。當合并相鄰的頂級變量聲明時,這是一個競爭條件。
- 已修復導致資產復制到錯誤輸出路徑的錯誤。
- 已修復一個涉及模板文字合并錯誤的縮小程序錯誤。
- 生成源映射時可能出現的競爭條件已修復。
- 一個允許生成的變量名以數字開頭的錯誤已經修復。
- 保存到磁盤后創建BuildArtifact對象時可能發生的崩潰已修復。
- 日志中的內存泄漏已修復。
- 改進了在為瀏覽器構建時使用內置Node.js建議將--target選項設置為Node或bun時的錯誤消息。
fetch()memory leak
在fetch()中發現的兩個內存泄漏已修復。
回調創建了兩個對Promise<Response>對象的強保留引用,這防止了它被垃圾收集。
輸入驗證邏輯可能會創建一個強保留的Promise<Response>并立即丟棄它,而不會釋放強引用。這防止了Promise<Response>被垃圾收集。
這很尷尬,我們已經提高了內存泄漏測試的測試覆蓋率,以確保這種情況不會再次發生。以下是內存泄漏的圖表,由@dimka3553提供:
Bun 0.6.4版本
官方我們發布了bun測試的改進、Node.js兼容性錯誤修復、console.log()改進、可修改時區、require.cache支持、bundler錯誤修復等。
bun測試速度提高80%
官方我們已經使bun測試速度提高了80%,尤其是在有很多小測試文件的情況下。
Bun過度安排垃圾收集器在每個文件上同步運行。它已經在堆大小發生變化時調度GC,所以這是不必要的。這導致內存使用量增長了9%左右,這很好,因為與其他具有相同代碼的測試運行程序相比,Bun使用的內存減少了2-4倍。
bun測試讀取.env.test和.env.test.local
- NODE_ENV=測試現在已正確設置。
- 環境變量可以從.env.test和.env.test.local文件中讀取。
bun test timeouts
現在,您可以通過傳遞--timeout或將第三個可選數字參數傳遞給test()來為測試設置超時。
import { test } from "bun:test";
test("i took too long", async () => {
await Bun.sleep(100);
// the last argument is a timeout in milliseconds
}, 50);
expect().toHaveLength() and expect().toBeEmpty()
現在支持expect().toHaveLength()和expect(。toBeEmpty()。這些測試匹配器可用于Blob、Buffer、File、Headers、Map、Set、String、TypedArray和類數組對象。
mport { expect, test } from "bun:test";
test("expect().toHaveLength()", () => {
expect([1, 2, 3]).toHaveLength(3);
expect([1, 2, 3]).not.toHaveLength(2);
// Works on Blob, Buffer, File, Headers, Map, Set, String, TypedArray, and Array-like objects, or anything with a .length property
expect(new Headers({ Origin: "https://bun.sh" })).toHaveLength(1);
});
test("expect().toBeEmpty()", () => {
expect([]).toBeEmpty();
expect([1]).not.toBeEmpty();
// Works on Bun.file() too
expect(Bun.file(import.meta.path)).not.toBeEmpty();
});
最后
一臺電腦,一個鍵盤,盡情揮灑智慧的人生;幾行數字,幾個字母,認真編寫生活的美好;
一 個靈感,一段程序,推動科技進步,促進社會發展。