❝
原文链接:Bun 1.0[1],2023.09.08,by Jarred Sumner, Ashcon Partovi, Colin McDonnell
❞

Bun 是一个全能的多功能工具包,用于运行,构建,测试和调试 JavaScript 和 TypeScript ,从单个文件到全栈应用程序。Bun 1.0 稳定版本已发布并适用于生产环境了。
❝
注意:Bun 目前还没有针对 Windows 推出稳定版本,想尝试的同学可以在 Mac 上试试。
❞
「安装 Bun:」
$ curl -fsSL https://bun.sh/install | bash
# 或是
$ npm install -g bun
「升级 Bun:」
$ bun upgrade
Bun 是一个全能工具包
我们热爱 JavaScript。它很成熟,发展也很快,开发者社区充满活力和激情。
然而,自从 Node.js 在 14 年前首次亮相以来,一层又一层的工具已经积累起来。就像任何在没有集中规划的情况下成长和发展的系统一样,JavaScript 真个工具链正在变得慢和变复杂。
Bun 为何存在?
Bun 的目标很简单消除了缓慢和复杂性,同时又不丢弃 JavaScript 的所有优点。你最喜欢的库和框架仍然可以正常使用,你也不需要忘记你熟悉的约定。
同时,Bun 也让你从很多的工具配置中解放出来。
「Node.js」 —— Bun 是 Node.js 的直接替代品,所以你不需要:
-
node
-
npx
——bunx
快 5 倍 -
nodemon
—— Bun 有内置的监听模式支持 -
dotenv
、cross-env
—— Bun 默认就会读取.env
文件
「Transpilers」 —— Bun 可以运行 .js
、.ts
、.cjs
、.mjs
、.jsx
和 .tsx
文件,可以替换:
-
tsc
——(但你可以保留它用于类型检查!) -
babel
、.babelrc
、@babel/preset-*
-
ts-node
、ts-node-esm
-
tsx
**Bundlers **—— Bun 是一个 JavaScript bundler,具有一流的性能并且兼容 esbuild 的插件 API,因此你不需要:
-
esbuild
-
webpack
-
parcel
、.parcelrc
-
rollup
、rollup.config.js
「包管理器(Package managers)」 —— Bun 是一个与 npm 兼容的包管理器,具有熟悉的命令。它会读取 package.json
并写入 node_modules
,就像其他包管理器一样,所以你可以替换:
-
npm
、.npmrc
、pakage-lock.json
-
yarn
、yarn.lock
-
pnpm
、pnpm.lock
、pnpm-workspace.yaml
-
lerna
「测试库(Testing libraries)」——Bun 是一个兼容 Jest 的测试运行器,支持快照测试、Mocking 和代码覆盖率,因此你不再需要:
-
jest
、jest.config.js
-
ts-jest
、@swc/jest
、babel-jest
-
jest-extended
-
vitest
、vitest.config.ts
虽然这些工具各自都很好(大部分),但将它们一起使用不可避免地会变脆弱以及缓慢的开发人员体验。他们做了很多多余的工作。当运行 jest 时,你的代码将被各种工具要解析 3 次以上!而将所有这些链接在一起所需的插件和适配器又需要一直维护。
Bun 是一个单一的集成工具包,有效避免了这些集成问题。其中,每个工具都提供了一流的开发人员体验,不管从从性能还是到 API 设计。
Bun 是一个 JavaScript 运行时
Bun 是一个快速的 JavaScript 运行时。它的目标是使构建软件的体验更快、更少挫折、也更有趣。
Node.js 的兼容性
Bun 是 Node.js 的直接替代品。这表示现有 Node.js 应用程序和 npm 包也能在 Bun 中工作。Bun 内置了对Node API 的支持,包括:
-
内置模块,像 fs
、path
、net
-
全局变量,像 __dirname
、process
-
Node.js 的模块解析算法(e.g. node_modules
)
虽然与 Node.js 完美兼容是不可能的,不过 Bun 可以运行几乎任何 Node.js 应用程序。
Bun 在 npm 上针对最流行的 Node.js 包的测试套件进行了测试。像 Express、Koa 和 Hono 这样的服务器框架就可以工作。最流行的全栈框架构建的应用程序也如此测试了一遍。总体来说,这些库和框架覆盖了 Node.js API 表面每一块领域的的重要部分。

❝
注意:有关 Node.js 兼容性的详细分类,请查看:bun.sh/nodejs[2]。
❞
速度
Bun 速度很快,启动速度比 Node.js 快 4 倍[3]。这种差异会在运行 TypeScript 文件时被放大,因为在 Node.js 中运行 TypeScript 之前需要先进行一次编译。

与使用 Google 的 V8 引擎构建的 Node.js 和其他运行时不同,Bun 是使用 Apple 的 WebKit 引擎构建的。WebKit 是 Safari 的引擎,每天有数十亿台设备使用它。它速度快、效率高,并且经过了几十年的战斗考验。
TypeScript 和 JSX 支持
Bun 在运行时中内置了 JavaScript 转译器。这表示你可以使用 Bun 直接运行 JavaScript、TypeScript,甚至是JSX/TSX 文件,而不需要安装任何依赖。
$ bun index.ts
# or
$ bun index.tsx
ESM 和 CommonJS 兼容性
从 CommonJS 到 ES 模块的过渡非常缓慢,而且充满了恐怖。在 ESM 引入之后,Node.js 花了 5 年时间才在没有 --experimental-modules
标志的情况下支持它。无论如何,整个生态系统仍然充满了 CommonJS。
Bun 始终支持这两种模块系统。无需担心文件扩展名,.js
vs .cjs
vs .mjs
,或在 package.json
中包含 "type": "module"
。
你甚至可以在同一个文件中使用 import
和 require()
,也能正常工作。
import lodash from "lodash";
const _ = require("underscore");
Web APIs
Bun 内置了对浏览器中可用的 Web 标准 API 的支持,例如 fetch
、Request
、Response
、WebSocket
和 ReadableStream
。
const response = await fetch("https://example.com/");
const text = await response.text();
你不再需要安装像 node-fetch
和 ws
这样的软件包。Bun 内置的 Web API 是用本机代码实现的,比第三方替代品更快、更可靠。
热重载
Bun 也支持使用 --hot
来启用热重载,这将在文件更改时重新加载你的应用程序,提升开发效率。
$ bun --hot server.ts
与硬重启整个进程的工具(如 nodemon
)不同,Bun 重新加载代码而不终止旧进程。这表示 HTTP 和WebSocket 连接不会断开,状态不会丢失。
插件
Bun 被设计成高度可定制的。
你可以定义插件来拦截导入并执行自定义加载逻辑。插件可以添加对其他文件类型的支持,如 .yaml
或 .png
。Plugin API 的灵感来自 esbuild,这表示大多数 esbuild 插件都能在 Bun 中工作。
import { plugin } from "bun";
plugin({
name: "YAML",
async setup(build) {
const { load } = await import("js-yaml");
const { readFileSync } = await import("fs");
build.onLoad({ filter: /.(yaml|yml)$/ }, (args) => {
const text = readFileSync(args.path, "utf8");
const exports = load(text) as Record<string, any>;
return { exports, loader: "object" };
});
},
});
Bun APIs
Bun 提供了一套高度优化的标准库,可以满足大多数开发人员的需求。
与 Node.js API 相比,Node.js API 是为了向后兼容而存在的,Bun 提供的原生 API 则被设计为速度和易用而生。
Bun.file()
使用 Bun.file()
延迟加载在特定路径上的 File
。
const file = Bun.file("package.json");
const contents = await file.text();
Bun.file()
返回 BunFile
类型文件,扩展自 Web 标准 File
API。文件内容可以以各种格式延迟加载。
❝
Bun 读取文件的速度比 Node.js 快 10 倍[4]。
❞
Bun.write()
Bun.write()
是一个单一的、灵活的 API,用于将几乎任何东西写入磁盘——不管是字符串、二进制数据、 Blobs
,甚至是 Response
对象。
await Bun.write("index.html", "<html/>");
await Bun.write("index.html", Buffer.from("<html/>"));
await Bun.write("index.html", Bun.file("home.html"));
await Bun.write("index.html", await fetch("https://example.com/"));
Bun.serve()
使用 Bun.serve()
启动 HTTP 服务器、WebSocket
服务器。它基于熟悉的 Web 标准 API
,如 Request
和 Response
。
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
});
❝
Bun 每秒处理的请求数是 Node.js 的 4 倍[5]。
❞
你也可以使用 tls
选项配置 TLS(针对 https
服务)。
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
tls: {
key: Bun.file("/path/to/key.pem"),
cert: Bun.file("/path/to/cert.pem"),
}
});
要支持 WebSockets 和 HTTP,只需在 websocket
中定义一个事件处理程序。与 Node.js 相比,它不提供内置的 WebSocket API,需要像 ws
这样的第三方依赖项。
Bun.serve({
fetch() { ... },
websocket: {
open(ws) { ... },
message(ws, data) { ... },
close(ws, code, reason) { ... },
},
});
❝
Bun 每秒发送的消息数量是 Node.js 上
ws
的 5 倍[6]。❞
bun:sqlite
Bun 内置了 SQLite 支持。它有一个受 better-sqlite3
启发的 API,但它是用原生代码编写的,以提高速度。
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // => { runtime: "Bun" }
❝
Bun 查询 SQLite 的速度比 Node.js 上的
better-sqlite3
快 4 倍[7]。❞
Bun.password
Bun 还支持一些你不想自己实现,但又常见且复杂的 API。
你可以使用 Bun.password
来使用 bcrypt 或 argon2 散列和验证密码,无需外部依赖。
const password = "super-secure-pa$$word";
const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh...
const isMatch = await Bun.password.verify(password, hash);
// => true
Bun 是一个包管理器
即使你不将Bun 作为运行时使用,Bun 的内置包管理器也可以加快你的开发工作流程。在安装依赖项时盯着 npm spinner 的日子一去不复返了。
Bun 可能看起来像你用惯了的包管理器。
$ bun install
$ bun add <package> [--dev|--production|--peer]
$ bun remove <package>
$ bun update <package>
安装速度
Bun 比 npm
、 yarn
和 pnpm
快几个数量级。它使用全局模块缓存来避免从 npm 注册表进行冗余下载,并使用每个操作系统上可用的最快系统调用。

运行脚本
你可能已经有一段时间没有直接使用 node
运行脚本了。相反,我们经常使用包管理器来与框架和 CLI 进行交互,以构建我们的应用程序。
$ npm run dev
你可以将 npm run
替换为 bun run
,以在每次运行命令时节省 150ms 毫秒。
这些数字可能看起来都很小,但当运行 CLI 时,感知差异是巨大的。运行 npm run
明显滞后:

而运行 bun run
时,感觉瞬间就完成了。

我们并不只是针对 npm。事实上, bun run <command>
也比 yarn 和 pnpm 更快。
「脚本运行程序」 | 「平均时长」 |
---|---|
npm run |
176ms |
yarn run |
131ms |
pnpm run |
259ms |
bun run |
7ms |
Bun 是一个测试运行程序
如果你以前用 JavaScript 编写过测试,那么可能比较熟悉 Jest,它开创了“expect”风格的 API。
Bun 有一个内置的测试模块 bun:test
,完全兼容 Jest。
import { test, expect } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});
你可以使用 bun test
命令运行测试。
$ bun test
同时,还能收获 Bun 运行时的所有好处,包括 TypeScript 和 JSX 的支持。
从 Jest 或 Vitest 迁移很容易。任何从 @jest/globals
或 vitest 导入的内容都将在内部重新映射到 bun:test
,因此即使没有代码更改,也能正常工作。
import { test } from "@jest/globals";
describe("test suite", () => {
// ...
});
在针对 zod[8] 测试套件的基准测试中,Bun 比 Jest 快 13 倍,比 Vitest 快 8 倍。

Bun 的匹配器是使用快速的原生代码实现的—— Bun 中 的 expect().toEqual()
比 Jest
快 100 倍[9],比 Vitest 快 10 倍。
要开始使用,你可以使用 bun test
加快 CI。在 Github Actions 中,使用官方的 oven-sh/setup-bun[10] action。
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v1
- run: bun test
更加人性化的是,Bun 会自动为测试失败添加注释,因此 CI 日志很容易阅读。

Bun 是一个打包程序
Bun是一个 JavaScript 和 TypeScript 打包器和压缩器,可为浏览器、Node.js 和其他平台打包代码。
$ bun build ./index.tsx --outdir ./build
Bun 的打包 API 深受 esbuild[11] 的启发,并提供了一个兼容的插件 API。
import mdx from "@mdx-js/esbuild";
Bun.build({
entrypoints: ["index.tsx"],
outdir: "build",
plugins: [mdx()],
});
Bun 的插件 API 是通用的,表示插件同时适用于打包器和运行时。因此,可以在这里使用之前的 .yaml
插件来支持打包期间的 .yaml
导入。
使用 esbuild 自己的基准测试,Bun 比 esbuild 快 1.75 倍,比 Parcel 2 快 150 倍,比 Rollup + Terser 快 180 倍,比 Webpack 快 220 倍。

由于 Bun 的运行时和打包程序是集成的,表示 Bun 可以做其他打包程序无法做的事情。
Bun 引入了 JavaScript 宏(JavaScript macros),这是一种在打包时运行 JavaScript 函数的机制。讲这些函数返回的值直接内联到打包文件中。
// index.ts
import { getRelease } from "./release.ts" with { type: "macro" };
// The value of `release` is evaluated at bundle-time,
// and inlined into the bundle, not run-time.
const release = await getRelease();
// release.ts
export async function getRelease(): Promise<string> {
const response = await fetch(
"https://api.github.com/repos/oven-sh/bun/releases/latest"
);
const { tag_name } = await response.json();
return tag_name;
}
$ bun build index.ts
// index.ts
var release = await "bun-v1.0.0";
这是一个打包 JavaScript 的新模式(new paradigm)。
更多
Bun 为 macOS 和 Linux 提供了原生版本,但有一个值得注意的缺失:Windows。以前,要在Windows 上运行 Bun,需要安装 Windows Subsystem for Linux。但现在不需要了。
这是第一次,我们很高兴能发布一个实验性的,原生的 Bun for Windows 版本。
虽然 Bun 的 macOS 和 Linux 版本已经可以投入生产,但 Windows 版本还是高度实验性的。目前,仅支持 JavaScript 运行时;包管理器、测试运行程序和捆绑器已被禁用,直到它们更稳定为止,性能也没有得到优化。
References
Bun 1.0: https://bun.sh/blog/bun-v1.0
[2]
bun.sh/nodejs: https://bun.sh/nodejs
[3]
比 Node.js 快 4 倍: https://twitter.com/jarredsumner/status/1499225725492076544
[4]
比 Node.js 快 10 倍: https://twitter.com/jarredsumner/status/1513878964531519494
[5]
是 Node.js 的 4 倍: https://github.com/oven-sh/bun/tree/main/bench/react-hello-world
[6]
5 倍: https://github.com/oven-sh/bun/tree/main/bench/websocket-server
[7]
快 4 倍: https://github.com/oven-sh/bun/tree/main/bench/sqlite
[8]
zod: https://github.com/colinhacks/zod
[9]
快 100 倍: https://twitter.com/jarredsumner/status/1595681235606585346
[10]
oven-sh/setup-bun: https://github.com/oven-sh/setup-bun
[11]
esbuild: https://esbuild.github.io/api/
原文始发于微信公众号(写代码的宝哥):Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/243827.html