Bun 1.0 正式发布,爆火的前端运行时,速度遥遥领先!

9 月 8 日,前端运行时 Bun 1.0 正式发布,如今,Bun 已经稳定并且适用于生产环境。Bun 不仅是一个专注性能与开发者体验的全新 JavaScript 运行时,还是一个快速的、全能的工具包,可用于运行、构建、测试和调试JavaScript和TypeScript代码,无论是从单个文件还是完整的全栈应用。 2022年,Bun 发布,随即爆火,成为年度最火的前端项目: Bun 的流行程度伴随着在去年夏天发布的第一个 Beta 版而爆炸性增长:仅一个月内,就在 GitHub 上获得了超过两万颗 Star。

Bun 不仅仅是一个运行时。它也是:

  • 一个包管理器 (类似 Yarn、 NPM、 PNPM)
  • 一个构建工具 (类似 Webpack、 ESBuild、 Parcel)
  • 一个测试运行器
  • ...

所以 Bun 可以通过读取 package.json 来安装依赖项。Bun 还可以运行脚本。不管它做什么都比其他工具更快。Bun 在 JavaScript 生态系统的许多方面都有新的尝试,其中的重点是性能。它优先支持标准的 Web API,如 Fetch。它也支持许多 Node.js APIs,使其能与大多数 NPM 包兼容。

安装 Bun:

javascript 复制代码
// npm
npm install -g bun

// brew
brew tap oven-sh/bun
brew install bun

// curl
curl -fsSL https://bun.sh/install | bash

// docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

更新 Bun:

javascript 复制代码
bun upgrade

下面就来看看 Bun 是什么,1.0 版本带来了哪些更新!

Bun:全能的工具包

JavaScript 成熟、发展迅速,并且有着充满活力和激情的开发者社区。然而,自14年前Node.js发布以来,JavaScript 的工具链变得越来越庞大和复杂。这是因为在发展过程中,各种工具被逐渐添加进来,但没有一个统一的集中规划,导致工具链缺乏整体性和效率,变得运行缓慢和复杂。

Bun 为什么会出现?

Bun的目标很简单,就是要消除JavaScript工具链的缓慢和复杂性,但同时保留JavaScript本身的优点。Bun希望让开发者继续使用喜欢的库和框架,并且无需放弃已经熟悉的规范和约定。

为了实现这个目标,可能需要放弃一些在使用Bun之后变得不再必要的工具:

  • Node.js :Bun 的一个可以直接替代的工具,因此不再需要以下工具:
    • node
    • npx:Bun 的 bunx 命令比 npx 快5倍。
    • nodemon:Bun 内置了监听模式,无需使用 nodemon
    • dotenvcross-env:Bun 默认支持读取.env文件的配置。
  • 转译器 :Bun 可以运行.js.ts、``.cjs.mjs.jsx.tsx文件,因此不再需要以下工具:
    • tsc:仍然可以保留它用于类型检查!
    • babel.babelrc@babel/preset-*:不再需要使用 Babel 进行转译。
    • ts-nodets-node-esm:Bun 可以直接运行 TypeScript 文件。
    • tsx:Bun可以直接运行 TypeScript 的 JSX 文件。
  • 构建工具 :Bun 具有一流的性能和与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
    • lern
  • 测试库 :Bun是一个支持Jest的测试运行器,具有快照测试、模拟和代码覆盖率等功能,因此不再需要以下测试相关的工具:
    • jest, jest.config.js
    • ts-jest, @swc/jest, babel-jest
    • jest-extended
    • vitest, vitest.config.ts

尽管这些工具都有自己的优点,但使用它们时往往需要将它们全部集成在一起,这会导致开发过程变得缓慢和复杂。而Bun通过成为一个单一的工具包,提供了最佳的开发者体验,从性能到API设计都力求做到最好。

Bun:JavaScript 运行时

Bun是一个快速的JavaScript运行时。旨在提供出色的性能和开发体验。它的设计旨在解决开发过程中的各种痛点,使开发者的工作更加轻松和愉快。

与Node.js兼容

Bun 是可以直接替代 Node.js 的。这意味着现有的 Node.js 应用和 npm 包可以在 Bun 中正常工作。Bun 内置了对 Node.js API 的支持,包括:

  • 内置模块,如fspathnet
  • 全局对象,如__dirnameprocess
  • Node.js 模块解析算法(例如node_modules

尽管与 Node.js 完全兼容是不可能的,特别是一些依赖于v8版本的特性,但 Bun 几乎可以运行任何现有的 Node.js 应用。

Bun经过了与最受欢迎的Node.js包的兼容性测试,支持与Express、Koa、Hapi等服务端框架以及其他流行的全栈框架的无缝集成。开发者可以放心地在Bun中使用这些库和框架,并享受到更好的开发体验。 使用Next.js、Remix、Nuxt、Astro、SvelteKit、Nest、SolidStart和Vite构建的全栈应用可以在Bun中运行。

速度

Bun的速度非常快,启动速度比 Node.js 快 4 倍。当运行TypeScript文件时,这种差异会更加明显,因为在Node.js中运行TypeScript文件需要先进行转译才能运行。 Bun在运行一个简单的"Hello World" TypeScript文件时,比在Node.js中使用esbuild运行速度快5倍。

Bun使用的是Apple的WebKit引擎,而不是像Node.js和其他运行时一样使用Google的V8引擎。WebKit引擎是Safari浏览器的核心引擎,每天被数十亿的设备使用。它经过了长时间的实际应用和测试,具备快速和高效的特性。

TypeScript 和 JSX 支持

Bun内置了JavaScript转译器,因此可以运行JavaScript、TypeScript甚至JSX/TSX文件,无需任何依赖。

javascript 复制代码
// 运行 TS 文件
bun index.ts

// 运行 JSX/TSX 文件
bun index.tsx

ESM 和 CommonJS 兼容

从CommonJS到ES模块的过渡一直是缓慢而充满挑战的。在引入ESM之后,Node.js花了5年时间才在没有--experimental-modules标志的情况下支持它。尽管如此,生态系统仍然充斥着CommonJS。

Bun 同时支持这两种模块系统。无论是使用CommonJS的.js扩展名、.cjs扩展名,还是使用ES模块的.mjs扩展名,Bun都会进行正确的解析和执行,而无需额外的配置。

甚至可以在同一个文件中同时使用importrequire()

javascript 复制代码
import lodash from "lodash";
const _ = require("underscore");

Web API

Bun 内置支持浏览器中可用的Web标准API,如fetchRequestResponseWebSocketReadableStream等。

javascript 复制代码
const response = await fetch("https://example.com/");
const text = await response.text();

开发者不再需要安装像node-fetchws这样的包。Bun内置的 Web API 是使用原生代码实现的,比第三方替代方案更快速和可靠。

热重载

Bun提供了热重载功能,可以在开发过程中实现文件的自动重新加载。只需在运行Bun时加上--hot参数,当文件发生变化时,Bun 就会自动重新加载你的应用,从而提高开发效率。

javascript 复制代码
bun --hot server.ts

与像nodemon这样完全重新启动整个进程的工具不同,Bun 在重新加载代码时不会终止旧进程。这意味着HTTP和WebSocket连接不会断开,并且状态不会丢失。

插件

Bun 被设计为高度可定制的。 可以定义插件来拦截导入操作并执行自定义的加载逻辑。插件可以添加对其他文件类型的支持,比如.yaml.png。插件API的设计灵感来自于esbuild,这意味着大多数esbuild插件在 sBun 中也可以正常工作。

javascript 复制代码
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 API

Bun内部提供了针对开发者最常用需求的标准库API,并对其进行了高度优化。与Node.js的API不同,Node.js的API存在着向后兼容的考虑,而Bun的原生API则专注于提供更快速和更易于使用的功能。

Bun.file()

使用Bun.file()可以懒加载位于特定路径的文件。

javascript 复制代码
const file = Bun.file("package.json");
const contents = await file.text();

它返回一个扩展了 Web 标准FileBunFile对象。文件内容可以以多种格式进行懒加载。

javascript 复制代码
Bun.serve({
  port: 3000,
  fetch(request) {
    return new Response("Hello from Bun!");
  },
});

Bun每秒可以处理的请求比 Node.js 多 4 倍。

也可以使用tls选项来配置TLS(传输层安全协议)。

javascript 复制代码
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"),
  }
});

Bun内置了对WebSocket的支持,只需要在websocket中定义一个事件处理程序来实现同时支持HTTP和WebSocket。而Node.js没有提供内置的WebSocket API,所以需要使用第三方依赖库(例如ws)来实现WebSocket的支持。因此,使用Bun可以更加方便和简单地实现WebSocket功能。

javascript 复制代码
Bun.serve({
  fetch() { ... },
  websocket: {
    open(ws) { ... },
    message(ws, data) { ... },
    close(ws, code, reason) { ... },
  },
});

Bun 每秒可以处理的消息比在 Node.js 上使用 ws 库多 5 倍。

bun:sqlite

Bun内置了对 SQLite 的支持。它提供了一个受到better-sqlite3启发的API,但是使用本地代码编写,以达到更快的执行速度。

javascript 复制代码
import { Database } from "bun:sqlite";

const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // => { runtime: "Bun" }

在 Node.js 上,Bun 执行 SQLite 查询操作的速度比better-sqlite3快 4 倍。

Bun.password

Bun 还支持一些常见但复杂的API,不用自己去实现它们。

例如,可以使用Bun.password来使用bcryptargon2算法进行密码哈希和验证,无需外部依赖。

javascript 复制代码
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的加载动画,现在可以通过Bun的包管理器更高效地进行依赖项的安装。

Bun可能看起来像你熟悉的包管理器:

javascript 复制代码
bun install
bun add <package> [--dev|--production|--peer]
bun remove <package>
bun update <package>

安装速度

Bun的安装速度比 npm、yarn 和 pnpm 快好几个数量级。它利用全局模块缓存来避免从npm注册表中重复下载,并使用每个操作系统上最快速的系统调用。

运行脚本

很可能你已经有一段时间没有直接使用 Node 来运行脚本了。相反,通常使用包管理器(如npm、yarn等)与框架和命令行界面(CLI)进行交互,以构建应用。

javascript 复制代码
npm run dev

你可以用bun run来替换npm run,每次运行命令都能节省 150 毫秒的时间。

这些数字可能看起来很小,但在运行命令行界面(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完全兼容。

javascript 复制代码
import { test, expect } from "bun:test";

test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});

可以使用bun test命令来运行测试:

javascript 复制代码
bun test

还将获得 Bun 运行时的所有优势,包括TypeScript和JSX支持。

从Jest或Vite迁移很简单。@jest/globalsvitest的任何导入将在内部重新映射到bun:test,因此即使不进行任何代码更改,一切也将正常运行。

javascript 复制代码
import { test } from "@jest/globals";

describe("test suite", () => {
  // ...
});

在与 zod 的测试套件进行基准测试中,Bun比Jest快13倍,比Vite快8倍。 Bun的匹配器由快速的原生代码实现,Bun中的expect().toEqual()比Jest快100倍,比Vite快10倍。

可以使用bun test命令来加快 CI 构建速度,如果在Github Actions中,可以使用官方的oven-sh/setup-bun操作来设置Bun

javascript 复制代码
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:构建工具

Bun是一个JavaScript和TypeScript的构建工具和代码压缩工具,可用于将代码打包成适用于浏览器、Node.js和其他平台的形式。

javascript 复制代码
bun build ./index.tsx --outdir ./build

Bun 受到了 esbuild 的启发,并提供了兼容的插件API。

javascript 复制代码
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函数。这些函数返回的值会直接内联到打包文件中。

javascript 复制代码
// 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;
}
javascript 复制代码
// index.ts
import { getRelease } from "./release.ts" with { type: "macro" };

// release的值是在打包时进行评估的,并且内联到打包文件中,而不是在运行时执行。
const release = await getRelease();
javascript 复制代码
bun build index.ts
// index.ts
var release = await "bun-v1.0.0";

Bun:可以做更多事

Bun 在 macOS 和 Linux 上提供了原生构建支持,但 Windows 一直是一个明显的缺失。以前,在 Windows 上运行 Bun 需要安装 Windows 子系统来运行Linux系统,但现在不再需要。

Bun 首次发布了一个实验性的、专为Windows平台的本地版本的 Bun。这意味着Windows用户现在可以直接在其操作系统上使用 Bun,而无需额外的配置。 尽管Bun的macOS和Linux版本已经可以用于生产环境,但Windows版本目前仍然处于高度实验阶段。目前只支持JavaScript运行时,而包管理器、测试运行器和打包工具在稳定性更高之前都将被禁用。性能方面也还未进行优化。

Bun:面向未来

Bun 1.0 只是一个开始。Bun 团队正在开发一种全新的部署JavaScript和TypeScript到生产环境的方式,期待 Bun 未来更好的表现!

相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax