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