Bun来了

前言

Bun 最近有多火:短短几天 star 数量就从 2k 涨到了现在的

长话短说,下面开始我们直接带走他 ~

什么是 Bun

Bun (读音类似于[bʌn],包子的意思) 是一个像 Node 或 Deno 这样的现代 JavaScript 运行时;

通俗一点讲就是你可以在 Bun 上运行 JavaScript 代码,你是不是在想这不是跟 Node 和 Deno 一样的吗,这也能火?

别急嘛,咱们往后看;

all-in-one

官方还称其为: all-in-one JavaScript runtime

所谓 all in one,是因为 Bun 和传统的 Node.js 这种传统的 javaScript 运行时 不同; Bun 提供了 打包、转译、安装和运行 JavaScript & TypeScript 项目的功能,内置原生打包器 (native bundler)、转译器、task runner、npm 客户端,以及数百个 Node.js API 和 Web API,包括约 90% 的 Node-API 函数(本机模块)、fs、path、Buffer 等。

这就意味着你可以实现在 Bun 上运行的大部分 Node API 和 Web API, 还可以在不需要使用 Webpack、Rollup、esbuild、babel 等工具的前提下直接运行 TypeScript 、JSX 了;

乍一看,是不是瞬间档次高了许多?

但是这样还不足以让你在同事、面试官的跟前吹 🐂 🍺

各位看官,您继续往下看…

为什么用 Bun

性能测试结果

  1. 服务器端渲染 React:每秒的 HTTP 请求数 162122_b5S9_2720166.png
  2. 加载一个大型数据表:每秒平均查询次数 162023_HRzw_2720166.png
  3. FFI:每秒操作数 162243_oeIL_2720166.png

根据上面 服务器端渲染、加载大型数据表、FFI 三个方面来对比,可见 Bun 可以说在性能方面是吊打 Node.js 和 Deno;

为什么快

  1. 引擎差异

不同于 Node.js 和 Deno,Bun 并没有基于 V8 引擎,而是使用了 JavaScriptCore 引擎,它的执行速度往往要比 V8 等更传统引擎要快。

  1. 语言差异

Bun.js使用的是新兴的系统编程语言 ZIG 编写的,主要通过手动内存管理对内存进行更细粒度的控制、无隐藏的控制流来提升程序的性能;

  1. 从零开始

在上两点的前提下,Bun.js 的大部分内容都是完全从零开始编写的,包括 JSX/TypeScript 转译器、npm 客户端、打包器、SQLite 客户端、HTTP 客户端、WebSocket 客户端等等。

注意:Zig 是一门系统级编程语言,专为稳定性、可维护性和性能而设计,是追求替代 C 语言在系统编程上的最佳地位。

内置兼容性

  • Web API 支持:对 fetch、WebSocket、 ReadableStream 等 API 都提供了内置支持;
  • Node.js模块Bun 实现了 Node.js 的模块解析算法,,以便我们可以在 Bun 中使用 npm 包,同时支持 ESM 和 CommonJS,但 Bun 内部使用 ESM
  • Bun.js 实现了大部分 Node-API (N-API),大部分 Node.js 原生模块及全局变量(比如Buffer 和 process)都可以正常工作;
  • 自动加载环境变量 .env 文件,不需要再 require("dotenv").load()
  • 附带一个内置的快速 SQLite3 户端 bun:sqlite
  • 内置 JavaScript、TypeScript、JSX 等(见下表)各种转译器;
    Input Loader Output
    .js JSX + JavaScript .js
    .jsx JSX + JavaScript .js
    .ts TypeScript + JavaScript .js
    .tsx TypeScript + JSX + JavaScript .js
    .mjs JavaScript .js
    .cjs JavaScript .js
    .mts TypeScript .js
    .cts TypeScript .js
    .toml TOML .js
    .css CSS .css
    .env Env N/A
    .* file string

通过上述大家能发现,Bun 的目标是想在浏览器之外运行 JavaScript,为我们的基础架构带来性能和复杂性的增强,并通过更好、更简单的工具提高开发人员的生产力。

快速上手

Mac/Linux 上安装

  1. 安装
    1
    curl https://bun.sh/install | bash
  2. 新建 http.js
    1
    2
    3
    4
    5
    6
         export default {
       port: 3000,
       fetch(request) {
         return new Response('Welcome to Bun!');
      },
     };
  3. 运行
    1
         bun run http.js
  4. 浏览器中打开:http://localhost:3000 即可

注意:如果使用 Linux,强烈推荐内核版本 5.6 或更高版本,但最低为 5.1.

windows上安装

由于 Bun 对 windows 用户不太友好,安装起来并很不容易;

Bun 的常见功能使用

1. 当做包管理器使用

  1. 通过 package.json 安装依赖
    1
         bun install
  2. 新增或删除 package.json 中的某个安装包
    1
    2
    3
    4
    5
         # 删除
     bun remove react
     
     # 安装
     bun add preact

147004342-571b6123-17a9-49a2-8bfd-dcfc5204047e.png

根据测试,在 Linux 上 bun install 运行安装包速度往往比 npm install 运行脚本快 20 - 100 倍。

2. 直接运行scripts脚本

  1. bun run 来代替 npm run
    1
    2
    3
    4
    5
    # Instead of "npm run clean"
    bun run clean

    # This also works
    bun clean
  2. 运行 package.json 中的脚本
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
          # package.json 
     {
       "name": "myapp",
       "scripts": {
         "clean": "rm -rf dist out node_modules"
      }
     }
     ​
     # 在终端中运行以下命令
     bun run clean

根据测试,bun 运行 package.json 脚本比 npm 运行 package.json 脚本快 30 倍。

3. 快速创建 Next.js 项目

  1. 快速创建
    1
    2
    3
    4
    5
    6
         # 创建
     bun create next ./app
     
     # 运行
     cd app
     bun dev # start dev server
  2. 关联一个已经存在的 Next.js 应用
    1
    2
    3
    4
         bun add bun-framework-next
     echo "framework = 'next'" > bunfig.toml
     bun bun # bundle dependencies
     bun dev # start dev server

注意:Next.js 的需多功能都支持,但是也有小部分暂时不支持,所以生成环境使用需谨慎。

4. 快速创建 React 项目

  1. 快速创建
    1
    2
    3
         bun create react ./app
     cd app
     bun dev # start dev server
  2. 关联现有的React项目
    1
    2
    3
    4
    5
    6
    7
    8
         # To enable React Fast Refresh, ensure it is installed
     bun add -d react-refresh
     
     # Generate a bundle for your entry point(s)
     bun bun ./src/index.js # jsx, tsx, ts also work. can be multiple files
     
     # Start the dev server
     bun dev

5. 运行 TypeScript

Bun 中,天然支持运行运行 TypeScript,无需配置,无需额外安装;

如果你导入一个.tsor.tsx文件,bun 会将它转换成 JavaScript;bun 还编译node_modules中的.ts.tsx文件;这是由 bun 内置了 TypeScript 转译器,且速度很快。

如果你想在全局使用对应的 API,安装 bun-typs 到你的项目即可

1
2
3
4
5
6
7
8
9
 # 安装
 bun add -d bun-types
 
 # 在tsconfig.json中使用
 {
   "compilerOptions": {
     "types": ["bun-types"]
  }
 }

6. 常用命令

  • bun add:等同于 yarn add 或 npm install
  • bun install:等同于 yarn install 或 npm install
  • bun run:类似于 npm run
  • bun create:通过该命令,可快速创建一个模板项目
  • bun bun:该命令会递归收集指定文件的导入依赖,然后生成包含这些信息的 node_modules.bun 文件
  • bun upgrade:要升级 bun,请运行bun upgrade

7. 配置文件 bunfig.toml

bunfig.toml 是 bun 的配置文件。

它允许您在 bunfig.toml 加载配置,而不是每次都将参数传递给命令行。在解析命令行参数之前加载配置文件,这意味着命令行参数可以覆盖这个配置。

下面是一个配置例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Set a default framework to use
# By default, bun will look for an npm package like `bun-framework-${framework}`, followed by `${framework}`
framework = "next"
logLevel = "debug"

# publicDir = "public"
# external = ["jquery"]

[macros]
# Remap any import like this:
# import {graphql} from 'react-relay';
# To:
# import {graphql} from 'macro:bun-macro-relay';
react-relay = { "graphql" = "bun-macro-relay" }

[bundle]
saveTo = "node_modules.bun"
# Don't need this if `framework` is set, but showing it here as an example anyway
entryPoints = ["./app/index.ts"]

[bundle.packages]
# If you're bundling packages that do not actually live in a `node_modules` folder or do not have the full package name in the file path, you can pass this to bundle them anyway
"@bigapp/design-system" = true

[dev]
# Change the default port from 3000 to 5000
# Also inherited by Bun.serve
port = 5000

[define]
# Replace any usage of "process.env.bagel" with the string `lox`.
# The values are parsed as JSON, except single-quoted strings are supported and `'undefined'` becomes `undefined` in JS.
# This will probably change in a future release to be just regular TOML instead. It is a holdover from the CLI argument parsing.
"process.env.bagel" = "'lox'"

[loaders]
# When loading a .bagel file, run the JS parser
".bagel" = "js"

[debug]
# When navigating to a blob: or src: link, open the file in your editor
# If not, it tries $EDITOR or $VISUAL
# If that still fails, it will try Visual Studio Code, then Sublime Text, then a few others
# This is used by Bun.openInEditor()
editor = "code"

# List of editors:
# - "subl", "sublime"
# - "vscode", "code"
# - "textmate", "mate"
# - "idea"
# - "webstorm"
# - "nvim", "neovim"
# - "vim","vi"
# - "emacs"
# - "atom"
# If you pass it a file path, it will open with the file path instead
# It will recognize non-GUI editors, but I don't think it will work yet

相关属性解释:

  • framework :指定默认使用的 framework 版本,bun 将根据 bun-framework-${framework} 格式找寻找 npm 包;
  • logLevel :指定 log 级别(可用值 errorwarninfodebug );
  • publicDir :指定 public 目录;
  • external :指定外部扩展,作用等同于 Webpack 的 externals;
  • macros :宏定义,用于替换 import 路径,比如: import { graphql } from 'react-relay'; 将被转换为 import { graphql } from "macro:bun-macro-relay/bun-macro-relay.tsx";
  • dev.port :指定服务的监听端口(默认 3000 );
  • define :作用等同于 Webpack 的 DefinePlugin;
  • loaders :指定各类文件的解析器;

当然,上述只是举例说明了一些在前端领域常见的一些情况,如果你还想了解更多的使用方法与案例,可查看:

关于 Bun 作者

作者 Jarred Sumner 高中辍学,曾在 Stripe 和 Thiel Fellowship 工作;

总结

  • 对于性能方面,值得一探究竟;
  • 版本较新,最新版本才 v0.2.2但是能否真正的用于生产,按照作者目前的原话是不建议的,因为由于内存泄露等问题,所以不建议在生产环境中使用,但是目前作者已经在 996 的紧急修复相关问题了;

不过作为一门能吊打 Node 和 Deno 的工具,咱们还是有必要去了解作为茶余饭后吹牛的资本的;


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!