Bun

Bun v1.1.41


Jarred Sumner · 2024年12月20日

我們正在舊金山招聘系統工程師,一同打造 JavaScript 的未來!

此版本修正了 12 個錯誤(解決了 196 個 👍)。由於 node:vm 相容性改進,JSDOM 和 happy-dom 的運作更加可靠。「bun build --compile」取得了 --windows-icon 和 --windows-hide-console 選項(僅限 Windows)。「bun install」取得了 --omit=dev|optional|peer 選項,並在 .npmrc 中加入。修正了「bun install」中的 hoisting 邊緣案例

安裝 Bun

curl
npm
powershell
scoop
brew
docker
curl
curl -fsSL https://bun.dev.org.tw/install | bash
npm
npm install -g bun
powershell
powershell -c "irm bun.sh/install.ps1|iex"
scoop
scoop install bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

升級 Bun

bun upgrade

JSDOM、happy-dom 和 vm 相容性改進

我們對 node:vm 實作進行了相容性改進,這使得 jsdomhappy-dom 在 Bun 中運作更加可靠。

JSDOM 修正

先前,JSDOM 中的 runScripts: "outside-only"runScripts: "dangerously"runInContext 選項不受支援。現在已支援。

happy-dom 修正

當您呼叫 window.requestAnimationFrame,或當您呼叫各種其他依賴於正確設定 this 值的方法時,happy-dom 不再拋出錯誤。

新增:Windows 單一檔案可執行檔中的圖示

單一檔案可執行檔現在支援 --windows-icon=./icon.ico 選項,以便在 Windows 上的可執行檔中嵌入圖示。

bun build --compile --windows-icon=./icon.ico ./index.ts --outfile=app.exe

感謝 @paperclover 實作此功能!

新增:在 Windows 單一檔案可執行檔中隱藏主控台視窗

現在,當執行單一檔案可執行檔時,您可以隱藏 Windows 上的主控台視窗。

bun build --compile --windows-hide-console ./index.ts --outfile=app.exe

新增:Bun.build 中的 throw: true

當建置失敗時,Bun.build 中的 throw: true 選項會拋出錯誤,而不是在 logs 陣列中傳回錯誤。

const build = Bun.build({
  entrypoints: ["./index.ts"],
  outdir: "./dist",
  throw: true,
});

我們將在 Bun v1.2 中將此行為設為預設值。

新增:「bun install」中的 --omit=dev|optional|peer 選項

我們希望 bun install 在使用 npm 的現有專案中「正常運作」。我們已經支援 package-lock.json 移轉(已有一段時間),這是朝該目標邁進的又一步。

bun install 現在支援

  • --omit=dev 忽略開發相依性(類似於 --production
  • --omit=optional 忽略選用相依性
  • --omit=peer 忽略同層級相依性
  • ...以及以上選項的任何組合

我們也為 .npmrcbunfig.toml 新增了對 includeexclude 的支援。

感謝 @dylan-conway 實作此功能!

新增:expect().toHaveBeenCalledOnce()

您現在可以使用 expect().toHaveBeenCalledOnce() 來檢查 mock 函數是否恰好被呼叫一次。

import { test, expect, mock } from "bun:test";

test("fn is called once", () => {
  const fn = mock(() => {});
  expect(fn).not.toHaveBeenCalledOnce();
  fn();
  expect(fn).toHaveBeenCalledOnce();
  fn();
  expect(fn).not.toHaveBeenCalledOnce();
});

'use strict' 現在是 CommonJS

有些 CLI 真的想欺騙 bundler 並取得目前模組的檔案路徑,執行 runtime require,或檢查目前模組是否為主模組。它們嘗試各種方法使其運作,例如

"use strict";

if (eval("require.main") === eval("module.main")) {
  // ...
}

關於 Bun 如何讓 CommonJS 和 ESM 互通「正常運作」的難處之一是存在許多模糊性。

考慮以下程式碼

console.log("123");

這是 CommonJS 還是 ESM? 無法判斷。

那麼,這個呢?

console.log(module.require("path"));

CommonJS,因為它使用 module.require 來取得 path 模組。

還有這個?

import path from "path";
console.log(path);

ESM,因為它使用 import

還有這個?

import path from "path";
const fs = require("fs");
console.log(fs.readFileSync(path.resolve("package.json"), "utf8"));

ESM,因為它使用 import,並且說它是 CommonJS 會破壞程式碼。我們希望簡化在 JavaScript 中建置東西的流程,所以就說是 ESM,不要吹毛求疵。

最後,這個呢?

"use strict";

console.log(eval("module.require('path')"));

先前,Bun 會說是「ESM」,因為當完全無法判斷時(包括當檔案副檔名不明確、package.json 中沒有「type」欄位、沒有 export、沒有 import、沒有 TLA 等等),這是我們的預設行為。

現在,Bun 會說是「CommonJS」,因為檔案頂端有 "use strict"

ES 模組始終處於嚴格模式,因此只有在檔案最初打算作為 CommonJS 時,才需要明確包含 "use strict"。現在大多數輸出 CommonJS 的建置工具都會在檔案頂端包含 "use strict" 指令。因此,當完全無法判斷檔案是 CommonJS 還是 ESM 時,我們可以將其用作最後的 heuristic。

先前,eval("require.main") 會拋出 ReferenceError,因為 ESM 內部 eval 的符合規範行為是 indirect(全域作用域),即使它不是全域作用域,Bun 也會在 transpilation 時將 ESM 中的 require 替換為 import.meta.require,因此無論如何程式碼都無法運作。因此,本著「您的程式碼應該可以正常運作」的精神,我們已將檔案頂端的 "use strict" 新增到我們認為是 CommonJS 的範疇中。

已修正:「bun install」進度列顯示安裝總計數

已修正:在「bun install」中,快取停用選用相依性時可能發生的無限迴圈

已修正一個可能發生的無限迴圈,該迴圈是由於停用選用相依性並使用已填入的快取進行安裝而導致的。

感謝 @dylan-conway 修正此問題!

已修正:「bun install」中無法解析的相依性邊緣案例

當使用平台特定的相依性或透過 --production 停用相依性時,在某些罕見情況下,bun install 會因錯誤處理無法解析的相依性而掛起。

這是由於我們沒有按相依性的「行為」(是選用的嗎?同層級的?開發用的?等等)對相依性進行排序所致。這導致不一致

感謝 @dylan-conway 修正此問題!

已修正:bun build 中的 --conditions=default

已修正當在 Bun.build 中使用 --conditions=default 時可能發生的崩潰問題。注意:default 條件在 Bun.build 中預設使用。

感謝 @paperclover 修正此問題!

已修正:util.styleText 支援顏色陣列

您現在可以將顏色陣列傳遞給 util.styleText,以使用多種顏色設定字串樣式。

const styledText = util.styleText(
  ["red", "bold", "underline"],
  "Hello, world!",
);

這使行為與 Node.js 一致

已修正:VSCode 中不必要的內嵌 sourcemap

當您安裝 Bun 的官方 VSCode 擴充功能時,Bun 會自動在 VSCode 的「問題」索引標籤中報告 runtime 錯誤,為您提供即時的編輯器內錯誤報告。

這涉及 WebKit inspector 連線,當您從 VSCode 終端機正常啟動 Bun 時,就會發生這種連線。

當 debugger 連線時,Bun 會在內部將內嵌 sourcemap 附加到 transpiled JavaScript 檔案,以便 debugger 可以找到原始原始碼並對應錯誤、訊息、中斷點檔案等。這對於偵錯很重要,但將這些 base64 編碼的 sourcemap 附加到每個載入的檔案會耗費您的記憶體和啟動時間。

這些 sourcemap 僅對於 debugger 是必要的,而對於 VSCode 中的「問題」索引標籤功能則不是(該功能會傳送預先 sourcemap 的錯誤,而不是在擴充功能中進行 sourcemap )。此版本在僅使用「問題」索引標籤時停用內嵌 sourcemap。

感謝 @riskymh 修正此問題!

已修正:CommonJS 模組載入中理論上的崩潰

已修正 CommonJS 模組載入中可能發生的假設性崩潰。

Bun 在載入每個檔案之前都會先進行 transpilation。

CommonJS 模組具有類似以下的函數包裝器

(function (exports, require, module, __filename, __dirname) {
  // module code
});

在 Bun 的 CommonJS 模組載入器中,我們沒有處理模組未評估為函數的情況。transpiler 始終輸出函數。話雖如此,理論上模組可能會評估為函數以外的其他內容,因此我們還是修正了它。

作為此修正的一部分,我們也將指定 module.requiremodule.require.resolve 函數的步驟移至在外部函數包裝器評估完成後而不是之前發生。理論上應該不會有可觀察到的行為差異,但如果您發現任何問題,請告知我們!

已修正:巨集的 import 命名空間和預設 import

您現在可以為巨集 import 命名空間和預設 import。

import myMacro from "at-build-time" with {type: "macro"};
import * as allMyMacros from "at-build-time" with {type: "macro"};

myMacro();
allMyMacros.myMacro();

感謝 @brainkim 修正此問題!

感謝 6 位貢獻者!