Bun v1.0.12 修復了 24 個錯誤,讓 Bun 的 CLI 說明選單更易於閱讀,新增了對 bun -e
、bun --env-file
、server.url
、import.meta.env
、expect.unreachable()
的支援,改進了對模組模擬的支援,允許在捆綁時匯入內建模組,並提高了 Node.js 相容性。
Bun 是一個速度極快的 JavaScript 執行時環境、捆綁器、轉譯器和套件管理器,集所有功能於一身。如果您錯過了,以下是 Bun 最近的一些變更
v1.0.8
- 修復了 138 個錯誤(解決了 257 個 👍 反應),使require()
的記憶體使用量減少了 30%,為bun test
新增了模組模擬,修復了更多bun install
錯誤v1.0.9
- 修復了 glibc 符號版本錯誤、非法指令錯誤、Bun.spawn 錯誤、對等依賴項安裝的邊緣案例以及 JSX 轉譯器錯誤修復v1.0.10
- 修復了 14 個錯誤(解決了 102 個 👍 反應),node:http 速度提高了 14%,Bun for Linux ARM64 的穩定性改進,bun install 錯誤修復和 node:http 錯誤修復v1.0.11
- 修復了 5 個錯誤,新增了Bun.semver
,修復了 bun install 中的錯誤,並修復了影響astro
和@google-cloud/storage
的錯誤
安裝 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
bun -e
評估腳本
Bun 現在支援 -e
標誌,它是 --eval
的縮寫,允許您在不建立檔案的情況下執行腳本。這對於您不想建立檔案的快速腳本非常有用,並且類似於 node -e
。
bun -e "console.log('Hello, JavaScript!')"
Hello, JavaScript!
bun -e
利用了 Bun 內建對 TypeScript 和 JSX 的支援
$ bun -e "console.log(<div>Hello, TSX</div> as React.ReactNode);"
<div>Hello, TSX</div>
最上層的 await 也有效
$ bun -e "console.write(await fetch('https://api.github.com/repos/oven-sh/bun').then(r => r.text()))"
{
"id": 357728969,
"node_id": "MDEwOlJlcG9zaXRvcnkzNTc3Mjg5Njk=",
"name": "bun",
"full_name": "oven-sh/bun",
"private": false,
"owner": {
"login": "oven-sh",
"id": 108928776,
...
bun --env-file <path>
覆寫要載入的 .env 檔案
Bun 的自動 .env
載入器最初在將近兩年前的 v0.0.x 中推出,而今天我們發布了對 --env-file
的支援,以覆寫要載入的特定 .env
檔案。這對於測試不同的環境非常有用。
如果您有想要載入到程序中的自訂環境變數,則可以使用 --env-file
來指定包含要載入到程序中的環境變數的檔案。您可以定義多個 --env-file
引數。
bun --env-file=.env.1 src/index.ts
bun --env-file=.env.abc --env-file=.env.def run build
您可以在 Bun 執行時環境中執行腳本時,或在執行 package.json 腳本時使用 --env-file
。
感謝 @otgerrogla 實作此功能。
server.url
我們新增了對 server.url
的支援,它會傳回一個 URL 物件,該物件定義 HTTP 伺服器的位置。當您想要取得伺服器的格式化 URL 時,這在測試中特別有用。
const server = Bun.serve({
port: 0, // random port
fetch(request) {
return new Response();
},
});
console.log("Listening...", `${server.url}`);
// Listening... https://127.0.0.1:1234/
用於存取環境變數的 import.meta.env
您現在可以使用 import.meta.env
存取環境變數,這是 Vite 等框架使用的一種模式。
console.log(import.meta.env.NODE_ENV); // "development"
import.meta.env
是 process.env
和 Bun.env
的別名。它的存在是為了與 JavaScript 生態系統的其他部分相容。
感謝 @otgerrogla 實作此功能。
expect.unreachable()
bun test
獲得了對 expect.unreachable()
的支援,如果到達程式碼路徑,它會擲回錯誤。這對於確保永遠不會呼叫函數非常有用。
import { expect, test } from "bun:test";
import { foo } from "my-lib";
test("enum handles every case", () => {
switch (foo()) {
case "a":
break;
case "b":
break;
default: {
// Now:
expect.unreachable();
// Previously:
// throw new Error("Unreachable");
}
}
});
改進的 CLI 說明輸出
我們重新設計了 Bun CLI 的說明選單,使其更易於閱讀和理解。
$ bun --help
Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.0.12 (904134cc))
Usage: bun <command> [...flags] [...args]
Commands:
run ./my-script.ts Execute a file with Bun
lint Run a package.json script
test Run unit tests with Bun
x prettier Execute a package binary (CLI), installing if needed (bunx)
repl Start a REPL session with Bun
install Install dependencies for a package.json (bun i)
add astro Add a dependency to package.json (bun a)
remove left-pad Remove a dependency from package.json (bun rm)
update backbone Update outdated dependencies
link [<package>] Register or link a local npm package
unlink Unregister a local npm package
pm <subcommand> Additional package management utilities
build ./a.ts ./b.jsx Bundle TypeScript & JavaScript into a single file
init Start an empty Bun project from a blank template
create @evan/duckdb Create a new project from a template (bun c)
upgrade Upgrade to latest version of Bun.
<command> --help Print help text for command.
Flags:
--watch Automatically restart the process on file change
--hot Enable auto reload in the Bun runtime, test runner, or bundler
--smol Use less memory, but run garbage collection more often
-r, --preload Import a module before other modules are loaded
--inspect Activate Bun's debugger
--inspect-wait Activate Bun's debugger, wait for a connection before executing
--inspect-brk Activate Bun's debugger, set breakpoint on first line of code and wait
--if-present Exit without an error if the entrypoint does not exist
--no-install Disable auto install in the Bun runtime
--install Configure auto-install behavior. One of "auto" (default, auto-installs when no node_modules), "fallback" (missing packages only), "force" (always).
-i Auto-install dependencies during execution. Equivalent to --install=fallback.
-e, --eval Evaluate argument as a script
--prefer-offline Skip staleness checks for packages in the Bun runtime and resolve from disk
--prefer-latest Use the latest matching versions of packages in the Bun runtime, always checking npm
-p, --port Set the default port for Bun.serve
-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)
--silent Don't print the script command
-v, --version Print version and exit
--revision Print version with revision and exit
--env-file Load environment variables from the specified file(s)
--cwd Absolute path to resolve files & entry points from. This just changes the process' cwd.
-c, --config Specify path to Bun config file. Default $cwd/bunfig.toml
-h, --help Display this menu and exit
(more flags in bun install --help, bun test --help, and bun build --help)
Learn more about Bun: https://bun.dev.org.tw/docs
Join our Discord community: https://bun.dev.org.tw/discord
$ bun install --help
Usage: bun install [flags] [...<pkg>]
Alias: bun i
Install the dependencies listed in package.json
Flags:
-c, --config Specify path to config file (bunfig.toml)
-y, --yarn Write a yarn.lock file (yarn v1)
-p, --production Don't install devDependencies
--no-save Don't update package.json or save a lockfile
--save Save to package.json (true by default)
--dry-run Don't install anything
--frozen-lockfile Disallow changes to lockfile
-f, --force Always request the latest versions from the registry & reinstall all dependencies
--cache-dir Store & load cached data from a specific directory path
--no-cache Ignore manifest cache entirely
--silent Don't log anything
--verbose Excessively verbose logging
--no-progress Disable the progress bar
--no-summary Don't print a summary
--no-verify Skip verifying integrity of newly downloaded packages
--ignore-scripts Skip lifecycle scripts in the project's package.json (dependency scripts are never run)
-g, --global Install globally
--cwd Set a specific cwd
--backend Platform-specific optimizations for installing dependencies. Possible values: "clonefile" (default), "hardlink", "symlink", "copyfile"
--link-native-bins Link "bin" from a matching platform-specific "optionalDependencies" instead. Default: esbuild, turbo
--help Print this help menu
-d, --dev Add dependency to "devDependencies"
--optional Add dependency to "optionalDependencies"
-E, --exact Add the exact version instead of the ^range
Examples:
Install the dependencies for the current project
bun install
Skip devDependencies
bun install --production
Full documentation is available at https://bun.dev.org.tw/docs/cli/install
$ bun build --help
Usage:
Transpile and bundle one or more files.
bun build [...flags] [...entrypoints]
Flags:
--compile Generate a standalone Bun executable containing your bundled code
--watch Automatically restart the process on file change
--target The intended execution environment for the bundle. "browser", "bun" or "node"
--outdir Default to "dist" if multiple files
--outfile Write to a file
--sourcemap Build with sourcemaps - 'inline', 'external', or 'none'
--format Specifies the module format to build to. Only "esm" is supported.
--root Root directory used for multiple entry points
--splitting Enable code splitting
--public-path A prefix to be appended to any import paths in bundled code
-e, --external Exclude module from transpilation (can use * wildcards). ex: -e react
--entry-naming Customize entry point filenames. Defaults to "[dir]/[name].[ext]"
--chunk-naming Customize chunk filenames. Defaults to "[name]-[hash].[ext]"
--asset-naming Customize asset filenames. Defaults to "[name]-[hash].[ext]"
--server-components Enable React Server Components (experimental)
--no-bundle Transpile file only, do not bundle
--minify Enable all minification flags
--minify-syntax Minify syntax and inline data
--minify-whitespace Minify whitespace
--minify-identifiers Minify identifiers
Examples:
Frontend web apps:
bun build ./src/index.ts --outfile=bundle.js
bun build ./index.jsx ./lib/worker.ts --minify --splitting --outdir=out
Bundle code to be run in Bun (reduces server startup time)
bun build ./server.ts --target=bun --outfile=server.js
Creating a standalone executable (see https://bun.dev.org.tw/docs/bundler/executables)
bun build ./cli.ts --compile --outfile=my-app
A full list of flags is available at https://bun.dev.org.tw/docs/bundler
$ bun test --help
Usage: bun test [...flags] [<pattern>...]
Run all matching test files and print the results to stdout
Flags:
--timeout Set the per-test timeout in milliseconds, default is 5000.
--update-snapshots Update snapshot files
--rerun-each Re-run each test file <NUMBER> times, helps catch certain bugs
--only Only run tests that are marked with "test.only()"
--todo Include tests that are marked with "test.todo()"
--coverage Generate a coverage profile
--bail Exit the test suite after <NUMBER> failures. If you do not specify a number, it defaults to 1.
-t, --test-name-pattern Run only tests with a name that matches the given regex.
Examples:
Run all test files
bun test
Run all test files with "foo" or "bar" in the file name
bun test foo bar
Run all test files, only including tests whose names includes "baz"
bun test --test-name-pattern baz
Full documentation is available at https://bun.dev.org.tw/docs/cli/test
$ bun run --help
Usage: bun run [flags] <file or script>
Flags:
--silent Don't print the script command
-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)
--watch Automatically restart the process on file change
--hot Enable auto reload in the Bun runtime, test runner, or bundler
--smol Use less memory, but run garbage collection more often
-r, --preload Import a module before other modules are loaded
--inspect Activate Bun's debugger
--inspect-wait Activate Bun's debugger, wait for a connection before executing
--inspect-brk Activate Bun's debugger, set breakpoint on first line of code and wait
--if-present Exit without an error if the entrypoint does not exist
--no-install Disable auto install in the Bun runtime
--install Configure auto-install behavior. One of "auto" (default, auto-installs when no node_modules), "fallback" (missing packages only), "force" (always).
-i Auto-install dependencies during execution. Equivalent to --install=fallback.
-e, --eval Evaluate argument as a script
--prefer-offline Skip staleness checks for packages in the Bun runtime and resolve from disk
--prefer-latest Use the latest matching versions of packages in the Bun runtime, always checking npm
-p, --port Set the default port for Bun.serve
--main-fields Main fields to lookup in package.json. Defaults to --target dependent
--extension-order Defaults to: .tsx,.ts,.jsx,.js,.json
--tsconfig-override Specify custom tsconfig.json. Default <d>$cwd<r>/tsconfig.json
-d, --define Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:"development". Values are parsed as JSON.
-l, --loader Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi
--no-macros Disable macros from being executed in the bundler, transpiler and runtime
--jsx-factory Changes the function called when compiling JSX elements using the classic JSX runtime
--jsx-fragment Changes the function called when compiling JSX fragments
--jsx-import-source Declares the module specifier to be used for importing the jsx and jsxs factory functions. Default: "react"
--jsx-runtime "automatic" (default) or "classic"
--env-file Load environment variables from the specified file(s)
--cwd Absolute path to resolve files & entry points from. This just changes the process' cwd.
-c, --config Specify path to Bun config file. Default <d>$cwd<r>/bunfig.toml
-h, --help Display this menu and exit
Examples:
Run a JavaScript or TypeScript file
bun run ./index.js
bun run ./index.tsx
Run a package.json script
bun run dev
bun run lint
Full documentation is available at https://bun.dev.org.tw/docs/cli/run
感謝 @colinhacks 和 @paperclover。
巨集現在支援內建模組
您現在可以使用 Bun 中的巨集在捆綁時匯入內建模組。
在捆綁時將檔案讀取到字串中
// file.ts
import { readFileSync } from "node:fs" with {type: "macro"};
export const contents = readFileSync("hello.txt", "utf8");
Build
bun build --target=browser ./file.ts
在捆綁時衍生程序
// spawn.ts
import { spawnSync } from "node:child_process" with {type: "macro"};
const result = spawnSync("echo", ["Hello, world!"], {encoding: "utf-8"}).stdout;
console.log(result); // "Hello, world!"
Build
bun build --target=browser ./spawn.ts
mock.module(...)
現在支援預設匯出
我們修復了一個錯誤,該錯誤阻止 mock.module
覆寫預設匯出。
import { mock } from "bun:test";
mock.module("node:fs", () => ({
default: {
readFileSync() {
return "Hello, world!";
},
},
}));
import fs from "node:fs";
// Previously, this would have tried to read from the file system:
console.log(fs.readFileSync("hello.txt")); // "Hello, world!"
mock.module(...)
現在支援重新匯出
我們修復了一個錯誤,該錯誤阻止 mock.module
覆寫重新匯出。
// # c.test.ts
import { mock } from "bun:test";
mock.module("./a.ts", () => ({
exportedFromB: 123,
}));
import { exportedFromB } from "./a.ts";
// # a.ts
import { exportedFromB } from "./b.ts";
export { exportedFromB };
// # b.ts
export const exportedFromB = 456;
// Previously, this would have returned 456:
console.log(exportedFromB); // 123
對於 ESM,這會更新即時繫結。對於 CommonJS 模組,變更將在下次 require
模組時套用。
已修復:轉譯器保留自訂指示詞
先前,如果您在檔案頂部有未知的指示詞,Bun 的轉譯器會將其視為無效程式碼並將其移除。此問題已修復。
"use client"; // <-- this line is preserved now
export const MyComponent = () => <div>Hello, world!</div>;
已修復:Dirent.name
setter 必須是字串
先前,如果您嘗試透過 Object.create(Dirent)
建立 node:fs
模組的 Dirent
類別的實例,則存取 name
屬性會擲回錯誤,因為它不是透過 new
建立的。
import { Dirent } from "node:fs";
const dirent = Object.create(Dirent);
dirent.name = "hello.txt";
console.log(dirent.name); // "hello.txt"
某些程式庫依賴此行為,並且已修復。
已修復:斷言失敗和崩潰
我們最近對 JavaScriptCore 版本進行了變更,以確保在偵錯組建中啟用斷言。這讓我們能夠修復先前導致崩潰或斷言失敗的各種錯誤。這也將有助於使 Bun 在未來更加穩定。
已修復的部分問題包括
process.mainModule
的潛在崩潰- 建構
Worker
時崩潰 - 呼叫
Server.close()
時崩潰 Bun.serve()
的崩潰,理論上可能在中止進行中的請求時發生Headers.prototype.getAll
中的斷言失敗,理論上可能導致崩潰module.require
&&module.reoslve
中的斷言失敗,理論上可能導致崩潰ServerWebSocket.close
中的斷言失敗,原因是錯誤地檢查了傳遞給函數的引數類型- 拒絕 Promise 時的斷言失敗,可能導致遺失堆疊追蹤
- 全域物件上
onerror
回呼中的斷言失敗,可能導致崩潰
已修復:在擲回例外狀況後 require()
中可能發生的崩潰
當透過 require()
載入的 CommonJS 模組在初始化期間擲回例外狀況,同時巢狀於許多其他也未完全初始化的模組中時,有時會發生的崩潰已修復。
此崩潰的一種表現方式是,當未安裝原生附加元件時,模組需要 sharp
,並且該模組巢狀於許多其他也未完全初始化的模組中。
是什麼原因造成的?
原始程式碼在擲回例外狀況之前被垃圾回收,並且假設原始程式碼在該點無法被垃圾回收。我們新增了遺失的 null 檢查以修復此問題。
已修復:使用 bun install
+ package-lock.json
時出現 ENOENT
我們修復了 bun install
中的邊緣案例,該案例會導致大量 ENOENT
錯誤。當不存在 bun.lockb
,但存在 package-lock.json
時,就會發生這種情況。
已修復:bun install
搭配包含 ~
的套件
我們修復了一個錯誤,如果套件的版本中包含 ~
,則 bun install
會失敗。此問題已修復,感謝 @Hanaasagi。
已修復:Bun 不會將引數轉發到生命週期腳本
我們修復了一個錯誤,Bun 會將引數傳遞給生命週期腳本。例如,如果您執行 bun run build --production
,Bun 會將 --production
傳遞給 prebuild
腳本,這可能會導致意外的失敗。
{
"scripts": {
"prebuild": "echo \"Building...\"",
"build": "bun scripts/build.ts"
}
}
之前
$ echo "Building..." --production
Building... --production
之後
$ echo "Building..."
Building...
感謝 @nektro 修復此問題。
已修復:bun:sqlite
的 .get() 方法中出現的掛起
先前,以下程式碼在快速連續呼叫約 5,000 次後可能會掛起
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.prepare("SELECT 1");
for (let i = 0; i < 10000; i++) {
query.get();
}
此問題已修復。
是什麼原因造成的?
用於 SQLite 陳述式的原型具有不正確的 JSType
指定。
JavaScriptCore 具有與每個堆積分配值相關聯的內部 JSType
標籤。此標籤在許多地方使用,包括 JIT。SQLite 陳述式使用了 FunctionType
而不是 ObjectType
,這導致 DFG JIT 錯誤地最佳化了 .get()
方法。這導致函數執行足夠多次以讓 DFG JIT 最佳化函數後掛起。
JavaScriptCore 有一個斷言捕獲了此錯誤,但我們未在開發中啟用斷言的情況下執行 JavaScriptCore。為了在未來捕獲此類錯誤,我們已在 JavaScriptCore(引擎)的偵錯組建中啟用了斷言,以用於 Bun 的偵錯組建。
已修復:使用 headers.raw()
時 Set-Cookie
標頭大小寫錯誤
我們修復了一個問題,即來自 node-fetch
的 headers.raw()
會傳回大小寫錯誤的 Set-Cookie
標頭。
之前
import { Headers } from "node-fetch";
const headers = new Headers({
"User-Agent": "Bun",
"Set-Cookie": "foo=bar",
});
console.log(headers.raw());
// { "user-agent": "Bun", "Set-Cookie": ["foo=bar"] }
之後
import { Headers } from "node-fetch";
const headers = new Headers({
"Set-Cookie": "foo=bar",
});
console.log(headers.raw());
// { "user-agent": "Bun", "set-cookie": ["foo=bar"] }
感謝 @cirospaciari 修復此問題。
已修復:AsyncLocalStorage
無法多次停用
存在一個錯誤,AsyncLocalStorage
無法多次停用。此問題已修復。
之前
import { AsyncLocalStorage } from "node:async_hooks";
const store = new AsyncLocalStorage();
store.enterWith(1);
store.disable();
console.log(store.getStore()); // undefined
store.enterWith(2);
store.disable();
console.log(store.getStore()); // 2
之後
import { AsyncLocalStorage } from "node:async_hooks";
const store = new AsyncLocalStorage();
store.enterWith(1);
store.disable();
console.log(store.getStore()); // undefined
store.enterWith(2);
store.disable();
console.log(store.getStore()); // undefined
感謝 @cirospaciari 修復此問題。
已修復:當 Promise 化時,fs.read()
傳回不正確的值
我們修復了一個錯誤,當使用 util.promisify(fs.read)
時,fs.read()
會傳回不正確的值。
之前
import fs from "node:fs";
import { promisify } from "node:util";
const read = promisify(fs.read);
const fd = await fs.promises.open("hello.txt");
const buffer = new Uint8Array(16);
const result = await read(fd, buffer, 0, 16, 0);
console.log(result); // 16
之後
import fs from "node:fs";
import { promisify } from "node:util";
const read = promisify(fs.read);
const fd = await fs.promises.open("hello.txt");
const buffer = new Uint8Array(16);
const result = await read(fd, buffer, 0, 16, 0);
console.log(result); // { bytesRead: 16, buffer }
感謝 @nektro 修復此問題。
在此過程中,我們還修復了
- Promise 化時的
fs.write()
- Promise 化時的
fs.writev()
- Promise 化時的
fs.readv()
已修復:HTTP 用戶端回應中遺失某些標頭時的錯誤
對於 HTTP/1.1,Content-Length
標頭和 Transfer-Encoding
標頭都是可選的。當省略這些標頭時,HTTP 用戶端應等待直到連線關閉,以判斷回應本文的長度(並隱含地停用 keep-alive)。
先前,Bun 未處理此情況,並將這些 HTTP 回應視為格式錯誤。
現在,當省略 Content-Length
和 Transfer-Encoding
標頭時,Bun 會正確處理此情況並停用 keep-alive。不建議省略這些標頭(keep-alive 是 HTTP/1.1 的重要最佳化,尤其是 TLS),但 Bun 現在可以處理這種情況。
已修復:bun install --yarn
有時會產生無效的 YAML
Bun 的 yarn.lock 檔案列印程式中存在一個錯誤,在某些情況下無法正確逸出識別碼。這會導致 bun install --yarn
產生 Yarn v1 無法剖析的 yarn.lock 檔案。請注意,從技術上講,yarn.lock 不是 YAML 檔案,它是一種客製化的 Yarn v1 特定格式(但說「YAML」更容易,因為它非常接近 YAML)。
已修復:允許對 crypto.subtle
進行 polyfill
先前,如果對 crypto.subtle
進行 polyfill,Bun 會擲回錯誤。有些套件依賴此行為,並且已修復。
已修復:bun init
會包含無效的 .gitignore
存在一個錯誤,bun init
會包含無效的 .gitignore
檔案。感謝 @Pierre-Mike,此問題已修復。
已修復:偵錯工具中的崩潰
在使用 bun --inspect
偵錯應用程式時,啟動時可能會發生崩潰,此問題已修復。
崩潰的原因是假設偵錯工具已啟動,但它可能尚未啟動。
已修復:有時 bun install 會二進制連結錯誤的版本
在某些情況下,bun install 可能會二進制連結錯誤版本的套件。我們先前未二進制連結到 my-dependency/node_modules/.bin
,而是偏好根 node_modules/.bin
。感謝 @dylan-conway,此問題已修復。
雜項
我們已升級到更高版本的 Zig。
感謝 19 位貢獻者!
- @antongolub
- @bh1337x
- @brettgoulder
- @cdfzo
- @cirospaciari
- @colinhacks
- @dottedmag
- @dylan-conway
- @Electroid
- @Hanaasagi
- @jaas666
- @Jarred-Sumner
- @joseph082
- @lorenzodonadio
- @nektro
- @otgerrogla
- @paperclover
- @Pierre-Mike
- @rupurt
- @SeedyROM
您也可以閱讀完整變更日誌。