Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS

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

Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS

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 有内置的监听模式支持
  • dotenvcross-env —— Bun 默认就会读取 .env 文件

「Transpilers」 —— Bun 可以运行 .js.ts.cjs.mjs.jsx.tsx 文件,可以替换:

  • tsc ——(但你可以保留它用于类型检查!)
  • babel.babelrc@babel/preset-*
  • ts-nodets-node-esm
  • tsx

**Bundlers **—— Bun 是一个 JavaScript bundler,具有一流的性能并且兼容 esbuild 的插件 API,因此你不需要:

  • esbuild
  • webpack
  • parcel.parcelrc
  • rolluprollup.config.js

「包管理器(Package managers)」 —— Bun 是一个与 npm 兼容的包管理器,具有熟悉的命令。它会读取 package.json 并写入 node_modules,就像其他包管理器一样,所以你可以替换:

  • npm.npmrcpakage-lock.json
  • yarnyarn.lock
  • pnpmpnpm.lockpnpm-workspace.yaml
  • lerna

「测试库(Testing libraries)」——Bun 是一个兼容 Jest 的测试运行器,支持快照测试、Mocking 和代码覆盖率,因此你不再需要:

  • jestjest.config.js
  • ts-jest@swc/jestbabel-jest
  • jest-extended
  • vitestvitest.config.ts

虽然这些工具各自都很好(大部分),但将它们一起使用不可避免地会变脆弱以及缓慢的开发人员体验。他们做了很多多余的工作。当运行 jest 时,你的代码将被各种工具要解析 3 次以上!而将所有这些链接在一起所需的插件和适配器又需要一直维护。

Bun 是一个单一的集成工具包,有效避免了这些集成问题。其中,每个工具都提供了一流的开发人员体验,不管从从性能还是到 API 设计。

Bun 是一个 JavaScript 运行时

Bun 是一个快速的 JavaScript 运行时。它的目标是使构建软件的体验更快、更少挫折、也更有趣。

Node.js 的兼容性

Bun 是 Node.js 的直接替代品。这表示现有 Node.js 应用程序和 npm 包也能在 Bun 中工作。Bun 内置了对Node API 的支持,包括:

  • 内置模块,像 fspathnet
  • 全局变量,像 __dirnameprocess
  • Node.js 的模块解析算法(e.g. node_modules

虽然与 Node.js 完美兼容是不可能的,不过 Bun 可以运行几乎任何 Node.js 应用程序。

Bun 在 npm 上针对最流行的 Node.js 包的测试套件进行了测试。像 Express、Koa 和 Hono 这样的服务器框架就可以工作。最流行的全栈框架构建的应用程序也如此测试了一遍。总体来说,这些库和框架覆盖了 Node.js API 表面每一块领域的的重要部分。

Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS
使用 Next.js,Remix,Nuxt,Astro,SvelteKit,Nest,SolidStart 和 Vite 构建的全栈应用程序都能在Bun中正常工作

注意:有关 Node.js 兼容性的详细分类,请查看:bun.sh/nodejs[2]

速度

Bun 速度很快,启动速度比 Node.js 快 4 倍[3]。这种差异会在运行 TypeScript 文件时被放大,因为在 Node.js 中运行 TypeScript 之前需要先进行一次编译。

Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS
Bun 运行“hello world”TypeScript 文件的速度比使用 Node.js 的 esbuild 快 5 倍

与使用 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"

你甚至可以在同一个文件中使用 importrequire(),也能正常工作。

import lodash from "lodash";
const _ = require("underscore");

Web APIs

Bun 内置了对浏览器中可用的 Web 标准 API 的支持,例如 fetchRequestResponseWebSocketReadableStream

const response = await fetch("https://example.com/");
const text = await response.text();

你不再需要安装像 node-fetchws 这样的软件包。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<stringany>;
      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,如 RequestResponse

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 上 ws5 倍[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 比 npmyarnpnpm 快几个数量级。它使用全局模块缓存来避免从 npm 注册表进行冗余下载,并使用每个操作系统上可用的最快系统调用。

Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS
通过安装 starter Remix 项目的依赖项进行基准测试

运行脚本

你可能已经有一段时间没有直接使用 node 运行脚本了。相反,我们经常使用包管理器来与框架和 CLI 进行交互,以构建我们的应用程序。

$ npm run dev

你可以将 npm run 替换为 bun run,以在每次运行命令时节省 150ms 毫秒。

这些数字可能看起来都很小,但当运行 CLI 时,感知差异是巨大的。运行 npm run 明显滞后:

Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS

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

Bun:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS

我们并不只是针对 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:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS
运行 zod 的测试套件

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:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS

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:一个快速、全能的工具包,用于运行、构建、测试和调试 JS 及 TS
从头开始打包 10 个 three.js 副本,输出 sourcemap 并且压缩

由于 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

[1]

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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!