大家好,我是若川。我持续组织了近一年的源码共读活动,感兴趣的可以 点此扫码加我微信 lxchuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外:目前建有江西|湖南|湖北|河南
籍前端群,可加我微信进群。公众号回复【相亲】关键词可以获取男生、女生的菜单~
原文链接:https://bun.sh/blog/bun-v1.0
作者:Jarred Sumner, Ashcon Partovi, Colin McDonnell
2023 年 9 月 8 日
以下是我(若川)简单翻译了一下。
转载需注明:翻译转载自@公众号:若川视野
Bun 1.0 终于来了。Bun 是一个快速、一体化的工具包,用于运行、构建、测试和调试 JavaScript 和 TypeScript,从单个文件到全栈应用程序。如今,Bun 已经稳定并可以投入生产。
安装 Bun
# crul
curl -fsSL https://bun.sh/install | bash
# npm
npm install -g 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
1Bun 是一个一体化工具包
我们喜欢 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
默认读取文件
转译器- Bun 可以运行.js
、.ts
、.cjs
、.mjs
、.jsx
和.tsx
文件,它们可以替换:
tsc
—(但您可以保留它以进行类型检查!)babel
,.babelrc
,@babel/preset-*
ts-node
,ts-node-esm
tsx
捆绑器— Bun 是一个 JavaScript 捆绑器,具有一流的性能和与 esbuild 兼容的插件 API,因此您不需要:
esbuild
webpack
parcel
,.parcelrc
rollup
,rollup.config.js
包管理器——Bun 是一个与 npm 兼容的包管理器,具有熟悉的命令。它读取您的package.json
内容并写入node_modules
,就像其他包管理器一样,因此您可以替换:
npm
,.npmrc
,package-lock.json
yarn
,yarn.lock
pnpm
,pnpm.lock
,pnpm-workspace.yaml
lerna
测试库— Bun 是一个与 Jest 兼容的测试运行器,支持快照测试、模拟和代码覆盖率,因此您不再需要:
jest
,jest.config.js
ts-jest
,@swc/jest
,babel-jest
jest-extended
vitest
,vitest.config.ts
虽然这些工具(大部分)本身都很好,但将它们一起使用不可避免地会造成脆弱性和缓慢的开发人员体验。他们做很多多余的工作;当你运行时jest
,你的代码将被各种工具解析3次以上!将所有东西缝合在一起所需的管道胶带、插件和适配器最终总是会磨损。Bun 是一个单一的集成工具包,可以避免这些集成问题。该工具包中的每个工具都提供了一流的开发人员体验,从性能到 API 设计。
2Bun 是一个 JavaScript 运行时
Bun 是一个快速的 JavaScript 运行时。其目标是让构建软件的体验更快、更少令人沮丧、更有趣。
Node.js 兼容性
Bun 是 Node.js 的直接替代品。这意味着现有的 Node.js 应用程序和 npm 包_只能在 Bun 中运行_。Bun 内置了对 Node API 的支持,包括:
内置模块,如
fs
、path
、 和net
,全局变量如
__dirname
和process
,以及 Node.js 模块解析算法。(例如
node_modules
)
虽然与 Node.js_完美_兼容是不可能的——看看你node:v8
——Bun 几乎可以在野外运行任何 Node.js 应用程序。Bun 针对 npm 上最流行的 Node.js 包的测试套件进行了测试。Express、Koa 和 Hono 等服务器框架就可以正常工作。使用最流行的全栈框架构建的应用程序也是如此。总的来说,这些库和框架涉及 Node.js API 表面的每个重要部分。
注意 - 有关 Node.js 兼容性的详细分类,请查看:bun.sh/nodejs。
速度
Bun 速度很快,启动速度比 Node.js快4 倍。这种差异仅在运行 TypeScript 文件时才会被放大,该文件需要转译才能由 Node.js 运行。
与使用 Google V8 引擎构建的 Node.js 和其他运行时不同,Bun 是使用 Apple 的WebKit引擎构建的。WebKit 是为 Safari 提供支持的引擎,每天有数十亿台设备使用。它快速、高效,并且经过了数十年的实战考验。
TypeScript 和 JSX 支持
Bun 有一个嵌入运行时的 JavaScript 转译器。这意味着您可以运行 JavaScript、TypeScript 甚至 JSX/TSX 文件,无需依赖项。
打字稿
JSX/TSX
bun index.ts
ESM 和 CommonJS 兼容性
从 CommonJS 到 ES 模块的过渡是缓慢且充满恐惧的。引入 ESM 后,Node.js 花了 5 年时间才在没有--experimental-modules
标记的情况下支持它。无论如何,生态系统仍然充满了 CommonJS。Bun 始终支持这两种模块系统。无需担心文件扩展名.js
vs.cjs
vs.mjs
,或包含"type": "module"
在您的package.json
.您甚至可以_在同一文件中_import
使用和require()
, 。它就是有效的。
import lodash from "lodash";
const _ = require("underscore");
网络 API
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 让您作为开发人员能够更轻松地提高工作效率。您可以运行 Bun 以--hot
启用热重载,这会在文件更改时重新加载您的应用程序。
bun --hot server.ts
与硬重启整个进程的工具不同nodemon
,Bun 会重新加载代码而不终止旧进程。这意味着 HTTP 和 WebSocket 连接不会断开,状态也不会丢失。
插件
Bun 的设计是高度可定制的。您可以定义插件来拦截导入并执行自定义加载逻辑。插件可以添加对其他文件类型的支持,例如.yaml
或.png
.插件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" };
});
},
});
3Bun API
Bun 附带高度优化的标准库 API,可满足开发人员最需要的功能。与为了向后兼容而存在的 Node.js API 相比,这些_Bun 原生_API 被设计为快速且易于使用。
Bun.file()
用于在特定路径上Bun.file()
延迟加载。File
const file = Bun.file("package.json");
const contents = await file.text();
它返回 aBunFile
,它扩展了 Web 标准File
。文件内容可以以各种格式延迟加载。
const file = Bun.file("package.json");
await file.text(); // string
await file.arrayBuffer(); // ArrayBuffer
await file.blob(); // Blob
await file.json(); // {...}
Bun 读取文件的速度比 Node.js快 10 倍。
Bun.write()
UseBun.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 写入文件的速度比 Node.js快 3 倍。
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 倍。
您还可以使用该tls
选项配置 TLS。
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"),
}
});
要支持 WebSocket 和 HTTP,只需在websocket
.与 Node.js 相比,Node.js 不提供内置的 WebSocket API,并且需要第三方依赖项,例如ws
.
Bun.serve({
fetch() { ... },
websocket: {
open(ws) { ... },
message(ws, data) { ... },
close(ws, code, reason) { ... },
},
});
Bun每秒可以提供比Node.js多5 倍的消息。ws
bun:sqlite
Bun 内置了对 SQLite 的支持。它有一个受 启发的 APIbetter-sqlite3
,但采用本机代码编写,速度更快。
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 快4倍better-sqlite3
。
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
4Bun 是一个包管理器
即使您不使用 Bun 作为运行时,Bun 的内置包管理器也可以加快您的开发工作流程。npm
安装依赖项时盯着那个旋转器的日子已经一去不复返了。Bun 可能_看起来_像你习惯的包管理器 -
bun install
bun add <package> [--dev|--production|--peer]
bun remove <package>
bun update <package>
——但感觉不像他们。
安装速度
npm
Bun 比、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 🚀 |
5Bun is a test runner
如果您以前用 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
,因此即使没有代码更改,一切都可以正常工作。
索引.test.ts
import { test } from "@jest/globals";
describe("test suite", () => {
// ...
});
在针对 测试套件的基准测试中zod
,Bun 比 Jest 快 13 倍,比 Vitest 快 8 倍。
Bun 的匹配器以快速本机代码实现 -expect().toEqual()
Bun比 Jest快100 倍,比 Vitest 快 10 倍。首先,您可以使用bun test
.在 Github Actions 中,使用官方oven-sh/setup-bun
操作。
.github/workflows/ci.yml
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 日志易于阅读。
6Bun 是一个捆绑器
Bun 是一个 JavaScript 和 TypeScript 捆绑器和压缩器,可用于捆绑浏览器、Node.js 和其他平台的代码。
命令行界面
bun build ./index.tsx --outdir ./build
它深受esbuild的启发,并提供兼容的插件 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 函数的机制。这些函数返回的值直接内联到您的包中。
索引.ts
发布.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();
命令行界面
bun build index.ts
// index.ts
var release = await "bun-v1.0.0";
这是捆绑 JavaScript 的新范例,我们很高兴看到您用它构建的内容。
7Bun more thing...
Bun 提供了适用于 macOS 和 Linux 的本机构建,但有一个值得注意的缺失:Windows。以前,要在 Windows 上运行 Bun,您需要安装适用于 Linux 的 Windows 子系统……但现在不再需要了。我们很高兴第一次发布适用于 Windows 的 Bun 的实验性本机版本。
=虽然 Bun 的 macOS 和 Linux 版本已可投入生产,但Windows 版本仍处于高度实验阶段。目前仅支持 JavaScript 运行时;包管理器、测试运行器和捆绑器已被禁用,直到它们变得更加稳定。性能也尚未优化。我们将在未来几周内快速改进对 Windows 的支持。如果您对 Windows 版 Bun 感到兴奋,我们鼓励您加入#windows
我们的Discord上的频道以获取更新。
8谢谢
如果没有 Bun 出色的工程师团队和不断壮大的贡献者社区,Bun 的 1.0 之旅就不可能实现。我们要感谢那些帮助我们到达这里的人。
Node.js 及其贡献者:软件是建立在巨人的肩膀上的。
WebKit 及其贡献者,尤其是Constellation:感谢您使 WebKit 变得更快,您太棒了。
过去两年来帮助构建Bun的近300名贡献者!
9下一步是什么?
Bun 1.0 仅仅是一个开始。我们正在开发一种将 JavaScript 和 TypeScript 部署到生产环境的新方法。如果您想帮助我们构建 JavaScript 的未来,我们正在招聘低级系统工程师。你也可以:
加入我们的 Discord 服务器,了解有关 Bun 的最新动态。
在 X/Twitter 上关注我们,了解 JavaScript 模因以及 Jarred 和团队的每日更新。
在 Github 上为我们加注星标——这样就可以支付账单了!(/秒)
安装Bun
# crul
curl -fsSL https://bun.sh/install | bash
# npm
npm install -g 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
自 v0.8 以来的变更日志
_如果您在 1.0之前_使用 Bun,则自 Bun 0.8 以来有一些变化。
现在支持 Next.js、Astro 和 Nest.js!
已弃用的
bun dev
命令已被删除。现在运行bun dev
将运行"dev"
package.json 中的脚本。
Bun 现在支持以下 Node.js API:
child_process.fork()
和工控机。fs.cp()
和fs.cpSync()
。fs.watchFile()
和fs.unwatchFile()
。中的 Unix 套接字
node:http
。
现在支持热重载Bun.serve()
。以前,只有将服务器定义为default export
.
服务器.ts
Bun.serve({
fetch(request) {
return new Response("Reload!");
},
})
命令行界面
bun --hot server.ts
大家好,我是若川。我持续组织了近一年的源码共读活动,感兴趣的可以 点此扫码加我微信 lxchuan12 参与,每周大家一起学习200行左右的源码,共同进步。