前言
跟着官网学习bun, 本文记录学习过程,供实时查阅。虽然 bun 和 node.js 很相似,但是也有很多不同的地方。现在主流的 vite, vue,Tarui, 等,都提供了用 bun 安装的方式。所以还是很值得学习探究的。
Bun的star数上升的很快,以下是Bun 与 Node.js 的GitHub的star数:
什么是Bun?
Bun 是 JavaScript 和 TypeScript 应用程序的一体化工具包。其核心是Bun运行时,这是一个快速的 JavaScript 运行时,旨在替代 Node.js 它用 Zig 编写,由 JavaScriptCore 提供支持,大大减少了启动时间和内存使用。
bun run index.tsx # 支持 ts 和 jsx
bun
命令行工具还实现了测试运行器、脚本运行器、和 与 Node.js兼容的软件包管理器,所有这些实现都比现有工具快得多,并且可以在现有的Node.js项目中使用,几乎不需要更改。
bun run start # 可以运行 start 脚本
bun install <pkg> # 可以安装依赖包
bun build ./index.tsc # 可以构建项目到浏览器使用
bun test # 可以运行测试
bunx cowsay 'Hello World!' # 可以执行包
什么是运行时?
JavaScript(或者更正式地说,ECMAScript) 只是编程语言的规范。任何人都可以编写一个JavaScript引擎,摄取有效的JavaScript程序并执行它。当今使用的两个最受欢迎的引擎是 V8(由谷歌开发) 和 JavaScriptCore(由苹果开发)。两者都是开源的。
浏览器
值得注意的是,浏览器附带了 JavaScript 运行时,这些运行时实现了一组特定的Web的API,这些API通过全局的 Window 对象公开。浏览器执行的任何 JavaScript 代码都可以使用这些API在当前网页的上下文中实现交互或动态行为。
Node.js
同样,Node.js是一个JavaScript运行时,可以在非浏览器环境中(如:服务器)中使用。除了执行读取/写入文件(node:fs)
和网络(node:net,node:http)
等 操作系统级任务的内置模块以外,Node.js 执行的 JavaScript 程序还可以访问一组特定的 Node.js的全局变量,如:Buffer,process 和 __dirname
Node.js还实现了基于 CommonJS 的模块系统和解析算法
,该算法早于 JavaScript 的本机模块系统。
Bun 被设计为 Node.js 的更快,更精简,更现代的替代品。
Bun 设计目标
Bun 从头开始设计,考虑到了今天的 JavaScript 生体系统。
- 速度。Bun进程的启动速度比 Node.js 更快。
- TypeScript 和 JSX 支持。您可以直接执行
.jsx
、.ts
、.tsx
文件;Bun会将这些文件转换为 javascript。 - ESM 和 CommonJS 兼容。Bun推荐使用ES模块,但同时也支持 CommonJS。
- Web标准API。Bun实现了标准的 Web API, 如:
fetch
、WebSocket
和ReadableStream
等。 - Node.js兼容性。除了支持 Node 风格的 模块解析外,Bun 还旨在与内置的 Node.js 全局(
(
process
、Buffer
) 和 (path
、fs
、http
等) 完全兼容。这是一项持续的努力,尚未完成。
Bun不仅仅是一个运行时。长期目标是成为一个有凝聚力的基础设施工具包,用于使用 JavaScript/TypeScript构建应用程序,包括软件包管理器、传输器、捆绑器、脚本运行器、测试运行器等。
Bun的目标是完整的与Node.jsAPI兼容。大多数用于Node.js环境的API 或者 npm软件包等用法,跟Bun大部分兼容,使用方式差不多的;Bun与Node.jsv20兼容情况查看
安装 Installing
Linux & macOS:
curl -fsSL https://bun.sh/install | bash
Linux & macOS: 如果要安装指定版本 v1.1.6
curl -fsSL https://bun.sh/install | bash -s "bun-v1.1.6"
Windows
Bun在Window上的安装条件:至少需要Windows 10版本1809,打开 Window PowerShell 执行如下命令(多尝试几次,成功后,配置要环境变量):
powershell -c "irm bun.sh/install.ps1 | iex"
Windows: 如果要安装指定版本 v1.1.6
iex "& {$(irm https://bun.sh/install.ps1)} -Version 1.1.6"
也支持 zip的安装方式
升级 Upgrading
bun upgrade
Homebrew users 用户: 使用 homebrew 有冲突的话,也可以尝试 brew upgrade bun
卸载 Uninstall
在 Linux & macOS 卸载:
rm -rf ~/.bun # for macOS, Linux, and WSL
在 Windows 上卸载:
powershell -c ~\.bun\uninstall.ps1
快速入门 QuickStart
先来简单的感受一下 bun;创建一个quickstart目录,用bun初始化工程,简单的脚本配置,跑起来看看,感受一下;
创建项目
创建bun项目,有两种命令:
bun init
和bun create
; 这边先使用bun init
创建 bun 项目;运行bun init
来创建一个项目。bun init
是一个交互式工具,只需按enter
即可接受每个提示的默认答案。
以下是使用终端命令创建的,当然也可以使用手动创建项目的文件夹,然后在项目文件夹下执行 bun init
来初始化;
webstorm展示项目目录以及运行情况;
**入口文件 .ts 和 .js 的区别:
由于我们的 入口点(入口文件) 是 一个
*.ts
文件,所以 bun 会为你 生成一个 tsconfig.json
。 如果你使用的是普通的 JavaScript
例:(*.js), 它将生成一个 jsconfig.json
。
即 入口文件后缀是 *.ts
的话,就会生成 tsconfig.json
, 入口文件后缀是 *.js
的话,就会生成 jsconfig.json
。
创建脚本
Bun 还可以从
package.json
中的scripts
添加脚本。
添加 start
脚本,方便快速可视化的运行。
Bun安装依赖包
如果使用 Bun的时候发现ts检查类型,有提示类型错误。可以尝试检查如下2个步骤:
①.使用命令bun add -d @types/bun
将@types/bun
安装为开发依赖项;
②.修改 tsconfig.json 的配置,添加内容到tsconfig.json
中的compilerOptions
中 ;
①.使用命令 bun add -d @types/bun
将 @types/bun
安装为开发依赖项;
@types/bun
是 Bun内置API的 TypeScript定义。这样就能够在 TypeScript文件中引用Bun全局,而不会在编辑器中看到错误。
bun add -d @types/bun
②.修改 tsconfig.json 的配置;将以下内容添加到
tsconfig.json
中的compilerOptions
中:
{
"compilerOptions": {
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
}
}
Bun 支持,顶级await, JSX 和 扩展 .ts 导入等内容。默认情况下 TypeScript不允许。 Bun推荐的
tsconfig.json
的compilerOptions
配置, 这样就可以在不看不到TypeScript编辑器警告的情况下使用这些功能:
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags
"noUnusedLocals": true,
"noUnusedParameters": true,
"noPropertyAccessFromIndexSignature": true
}
}
创建简单的HTTP服务器
使用
Bun.serve({})
来创建一个简单的 HTTP服务器,然后用浏览器打开。
如何创建快速Bun项目
创建 bun 模版项目,可以使用两种命令:
bun init
和bun create
;以下说明这个两个命令的适用情况,以及执行命令发生了什么?
bun init
bun init
是 一种 使用交互式命令,快速创建 空的 Bun 项目 方式; 适用于 创建 一个 全新的 空的 Bun项目 模版;
bun init
命令,创建过程如下:
可以按
enter
回车键,接受每个提示的默认答案,当然可以输入答案修改;
也可以使用 bun init
创建命令,可以通过传递命令参数 -y
或 --yes
标志,即命令: bun init -y
或 bun init --yes
的方式,默认接受所有默认值的方式,快速创建空的Bun项目模板;
bun init
工作的过程:
使用
bun init
命令创建空项目:项目目录结构:
执行 bun init
是如何工作的?
它创建:
- 名称默认为当前目录名称的
package.json
; tsconfig.json
文件或jsconfig.json
文件,取决于入口点是否是TypeScript文件;- 默认为
index.ts
的入口点,除非存在任何index.{tsx, jsx, js, mts, mjs}
或package.json
指定module
或main
字段; - 一个
README.md
文件; - 一个
bun.lockb
bun 的 lock 文件; 最后,它运行bun install
来安装@types/bun
依赖;
bun create
其实你可以不需要
bun create
就可以使用 bun , 你根本不需要任何配置。这个命令的存在是为了使开发变得更快,更容易。适用于创建本地模板、来自于npm的模板(从npm上下载的bun项目模板到磁盘)、来自于GitHub的模板(从GitHub上下载bun的项目到磁盘);
注意:
直接使用 例如:
bun create my-bun-app
创建新的项目,bun会尝试从npm源上查找my-bun-app项目
,不存在就会报错
;
远程模板
使用
bun create
(假设没有同名的本地模板的情况下)下载远程模板到本地磁盘,下载源主要来自于npm
和GitHub
;
从npm源下载(From npm)
使用
bun create
可以从 npm源 下载bun项目到磁盘。
命令格式如:bun create <template> [<destination>]
使用bun create
下载 remix
, 可以执行如下两个效果相同的命令:
bun create remix
# 或
bunx create-remix
- 运行
bun create remix
命令,过程: - 运行
bun create remix
后, 磁盘的工程目录结构:
大家看官网的时候会发现:
svelte.dev官网;因为bun几乎兼容node
,虽然这项兼容工作还在不断的持续进行,这就意味着一般可以使用 npm create
、npm init
或 npx
, 都可以尝试使用 bun create
命令;
Vue官网Vue官网提供了
bun create
的方式,快速创建Vue模版工程:
Vite官网, Vite 也是提供了
bun create vite
的方式;
现在市场上主流框架 或库 大都可以使用 bun create
方式,来快速创建它的模版工程;
综上所述,以下我们以 Vue 和 Svelet 为例,使用 bun create 快速创建它的模版工程目录:
使用 bun create svelte@latest my-svelte-app
;创建一个使用最新 SvelteKit 模板:
使用 bun create vue@latest my-vue-project
; 创建一个使用最新 vue 模版的项目:
从GitHub源下载(From Github)
bun create
可以将GitHub repo
(Github仓库) 的内容,下载到磁盘;这个过程可能会稍微久一点,下载的过程可能会由于网络等原因,在 bun install 的时候,有些依赖包会安装失败,失败的话重新install下。和git clone
类似。但是bun create 会自动 install
;
命令格式如:
bun create <user>/<repo>
bun create github.com/<user>/<repo>
可选地指定目标文件夹的名称。如果没有指定目的地,将使用repo(仓库)协议名称。
bun create <user>/<repo> mydir
bun create github.com/<user>/<repo> mydir
演示使用 bun create github.com/<repo>
命令的过程:
下载完成后的工程目录 和 Github仓库中的文件一致:
Bun将执行以下步骤:
- 下载模板
- 将所有模板文件复制到目标文件夹中
- 使用
bun install
安装依赖项。 - 初始化一个新的Git repo协议。使用
--no-git
标志选择退出。 - 运行模板配置的
start
脚本(如果已定义)。
默认情况下,Bun不会覆盖任何现有文件。使用--force
标志覆盖现有文件。
本地模板
从本地模板下载From a local template。与远程模板不同,使用本地模板运行
bun create
将删除整个目标文件夹(如果它已经存在)!小心点。
Bun的模板可以扩展到支持本地文件系统上定义的自定义模板。这些模板应该位于以下目录之一:
$HOME/.bun-create/<name>
:全局模板<project root>/.bun-create/<name>
:特定于项目的模板
注意—您可以通过设置BUN_CREATE_DIR
环境变量自定义全局模板路径。
要创建本地模板,请导航到$HOME/.bun-create
,并创建一个具有所需模板名称的新目录。
cd $HOME/.bun-create
mkdir foo
cd foo
然后,在该目录中创建一个包含以下内容的package.json
文件:
{
"name": "foo"
}
您可以在文件系统的其他地方运行bun create foo
,以验证Bun是否正确找到您的本地模板。
设置逻辑
您可以在本地模板package.json
的"bun-create"
部分中指定安装前和安装后设置脚本。
{
"name": "@bun-examples/simplereact",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"bun-create": {
"preinstall": "echo 'Installing...'", // a single command
"postinstall": ["echo 'Done!'"], // an array of commands
"start": "bun run echo 'Hello world!'"
}
}
支持以下字段。其中每一个都可以对应一个字符串或字符串数组。命令数组将按顺序执行。
字段 | 描述 |
---|---|
postinstall | 安装依赖项后运行 |
preinstall | 在安装依赖项之前运行 |
克隆模板后,bun create
将自动从package.json
中删除"bun-create"
部分,然后再将其写入目标文件夹。
bun create
命令标志
bun create
命令后面,可以带以下标志参数;例:bun create vue@latest --no-install
;
标志 | 描述 |
---|---|
--force | 覆盖现有文件; |
--no-install | 跳过安装 node_modules 和 任务; |
--no-git | 不要初始化git存储库; |
--open | 完成后启动并打开浏览器; |
运行时 RunTime
bun run
bun
命令可以被用来执行 JavaScript、TypeScript文件,package.json、scripts以及可执行包等。
Bun性能:
Bun被设计为快速启动 和 快速运行。
Bun使用苹果为Safari开发的 JavaScriptCore 引擎
,在大多数情况,启动和运行性能比 Node.js和基于Chromium的浏览器使用的引擎
V8快。它的 transpiler 和 runtime 是用 Zig 编写的,Zig是一种现代的高性能语言,在Linux上,这转化为启动时间比Node.js快 4 倍。
运行一个文件
还记得吗? node 也可以执行一个文件,例:
node index.js
, bun 也可以运行一个文件,感觉 bun 会比 node 执行的快一点;
回忆一下node运行一个文件:
bun 执行源文件,执行命令,如:bun run index.js
bun支持开箱即用的TypeScript 和 JSX
。每个文件在执行前都会由Bun的快速原生编辑器实时传输。
所以 bun 可以直接执行运行 js文件、 ts文件、tsx文件、 jsx 文件。
使用
bun run
命令,或者 可以直接 省略run
关键字,它的行为是相同的;即例如: bun index.js
;
--watch
需要在监视模式下运行文件,请使用
--watch
标志。**注意:这个 和 node 是不同的,使用bun run
时,在
bun后面立即放置标志
; 因为命令末尾出现的标志将被忽略; **
正确语法: bun --watch run dev
(✔️)
错误语法: bun run dev --watch
(❌)
这就意味着,我们在监视模式下运行文件,是实时编译的;
运行package.json
的scripts
与
npm run <scripts>
或yarn <scripts>
用法类似;我们可以在package.json
中配置命名scripts
要运行的命令 和 执行的命令行;然后使用bun run <scripts>
来执行这些脚本。
注意:如果命名的命令 和 Bun的内置命令名称冲突(和Bun的内置命令名称相同 install, dev, upgrade等), 内置命令优先;
要查看可用的scripts脚本列表,请在没有任何参数的情况下运行bun run
。
bun run -
从 stdin 到管道代码, 为了方便起见,在使用
bun run -
时,所有代码都被视为支持JSX的TypeScript。
-
bun run -
运行您从 stdin 读取 JavaScript、TypeScript、TSX或JSX,并执行它,而无需写入临时文件。 -
还可以使用
bun run -
将文件重定向到Bun中。例如,像运行.ts
文件一样运行.js
文件;即 可以通过管道,将内容写入到文件中并输出;
bun run --smol
在内存受限的环境中,使用
--smol
标志,能减少内存使用;这样会导致垃圾回收器更频繁地运行,这可能会减慢执行速度,然而,它在内存有限的环境中非常有用。Bun根据可用内存(考虑C组 和 其他内存限制)自动调整垃圾回收器的堆大小,有和没有--smol
标志,着对于堆大小增长更慢的情况非常有用。
命令格式:bun --smol run index.tsx
对文件类型的支持
Bun 原生支持开箱即用的TypeScript。所有文件在执行前都有Bun的快速原生转换器进行实时转换·
(Bun的内部编译器在执行前的时候会将 .jsx, .tsx, .ts文件转换成普通的 js.)
。与其他构建工具类似,Bun不执行类型检查;类型检查受到tsconfig.json
配置文件的影响。
- Bun支持
.js
文件、.jsx
文件、.ts
文件、.tsx
文件类型,可以直接运行或者执行; - 支持 文本文件 可以作为字符串导入;
- 支持 JSON 和 TOML 文件 可以直接从源文件导入。内容将作为 JavaScript对象载入 并返回;
- (实验性功能) Bun 对 WASI(WebAssembly系统接口) 有实验性的执行。使用 Bun运行
.wasm
二进制文件; - 对
SQLite
支持将 sqlite 数据库直接导入到你的代码中,Bun 将自动加载数据库 并 返回 Database 对象; - 支持配置 自定义 loaders ,配置插件,扩展对其他类型文件的支持;
对TypeScript的支持
Bun 可以直接执行
.ts
和.tsx
文件,就像执行 普通的JavaScript一样,无需额外的配置。如果 我们 import.ts
或.tsx
文件(或者export这些文件变成npm模块),Bun在内部会将这些转换为JavaScript。然后执行。
Bun会读取 tsconfig.json 的规则,以确定如何转换。
- 在解析模块的时候,Bun在运行时,遵守的是
tsconfig.json
中定义的compilerOptions
的paths
的 路径映射; - Bun 将使用
baseUrl
来解析模块路径; - Bun还能正确的解析,从
data.ts
中,导入的问题;
data.ts
index.ts// data.ts export const foo = "Hello world!"
import { foo } from "data"; console.log(foo); // => "Hello world!"
对 JSX 的支持
Bun支持开箱即用的
.jsx
和.tsx
文件。 Bun的内部编译器在执行前会将 JSX语法转换为普通的 JavaScript;
Bun会读取 tsconfig.json
或 jsconfig.json
配置文件,以便确定如何在内部执行 JSX 的转换,为了避免使用其中任何一个,也可以在bunfig.tom
中定义;
bunfig.toml
bunfig.tom
是Bun 的配置文件
,Bun的行为可以使用bunfig.toml
进行配置。一般来说,Bun依靠package.json
和tsconfig.json
等预先存在的配置文件来配置其行为。bunfig.toml
仅用于配置Bun的特定的东西。这个文件是可选的。即使没有配置它,Bun也是开箱即用的。
本地配置
一般来说,建议将
bunfig.toml
文件 与 你的package.json
文件 一起添加到项目的根目录
中的;
全局配置
要全局配置Bun, 可以在以下路径之一创建
.bunfig.toml
文件:
全局配置可以在以下路径之一配置 创建 .bunfig.toml
文件:
$HOME/.bunfig.toml
$XDG_CONFIG_HOME/.bunfig.toml
如果Bun检查到,全局和本地都有bunfig
, 会将它们 浅合并,局部的覆盖全局。
环境变量
一般来说,使用Bun,你不再需要
dotenv
或dotenv-expand
, 因为Bun会自动读取.env
文件,并提供以编程的方式读取 和 写入环境变量的方法。此外,Bun运行时行为的某些方面可以使用Bun特定的环境变量进行配置。
读取环境变量
访问当前环境变量有如下3种方式:
process.env
, 使用方式,例:process.env.FOO
;import.meta.env
, 使用方式,例:import.meta.env.FOO
;Bun.env
, 使用方式,例:Bun.env.FOO
;
使用 bun --print process.env
命令, 可以将所有当前设置的环境变量打印到命令行;
使用
bun --print Bun.env
和bun --print import.meat.env
目前也是可以打印的;
注意:
- 目前可以打印
.env
,.env.local
,.env.development
中的环境变量,自定义.env.XX
好像访问不了环境变量。 - 如.env文件 设置设置了同名的环境变量名,会取值 Bun读取的优先级顺序高的.env文件;Bun读取.env文件的优先级,在设置环境变量章节有说明;
设置环境变量
一般
.env
类型的文件,都是创建于项目的根目录下的;
Bun会自动以下文件,按照读取的优先级的递增顺序 列出:
.env
:优先级最低.env.production
,.env.development
,.env.test
(取决于NODE_ENV
的值)# 即需要在该.env文件头位置定义 NODE_ENV=development, 否则环境变量可能无法被访问到; # env.development NODE_ENV=development FOO=xxx
.env.local
:优先级最高
创建.env文件:
.env,.env.production,.env.development,.env.test,.env.local
都是在项目根目录下创建的
;
设置如何设置环境变量
:
-
环境变量一般是
以大写的字母组成变量
; 格式如:KEY=value
; 常规定义value不需要带引号;value的数据类型是 string
;FOO=hello BAR=world
-
Bun支持使用双引号,单引号,反引号 定义环境变量的值,适用于值不连贯带空格的字符串:
FOO='hello' FOO="hello" FOO=`hello` # 更适用于 不连贯有空格的的字符串 BAR='hello word hello bun'
-
环境变量会自动扩展,即:可以在环境变量中可以使用
$
来引用之前定义的环境变量:FOO=world # 使用 $ 来引用上面的 FOO环境变量,所以 BAR 的值是 helloworld BAR=hello$FOO
使用
$
来引用之前定义的环境变量,这对于构造连接字符串和复合值很有用:SERVER_HOST=127.0.0.1 SERVER_PORT=8080 # 使用$引用上面的环境变量,所以 SERVER_URL的值是 http://127.0.0.1:8080 SERVER_URL=http://$SERVER_HOST:$SERVER_PORT
-
因为
$
被用于引用之前定义的环境变量,那么要输出$
可以通过使用反斜杠来转义$
,即:使用反斜杠转义可以输出$
:FOO=world # 使用转义符 转义 $, BAR的值是 “hello$FOO” BAR=hello\$FOO
-
还可以通过将属性分配给
process.env
的方式,来设置环境变量; 例:process.env.KEY = value
来设置环境变量:process.env.FOO = "hello";
-
在bun运行的时候,可以通过
手动指定.env文件
的方式:
Bun 支持
--env-file
来覆盖要加载的特定的.env
文件。在bun的运行时或者运行 package.json脚本时,可以使用--env-file
的方式,来指定要运行的 .env文件
;
直接使用bun命令,在终端运行时指定--env-file
:
在项目根目录下创建.env.a
,.env.b
并设置FOO的值,然后在index.ts
中使用process.env.FOO
输出值,在终端使用命令运行;
.bash bun --env-file=.env.b index.ts # 或 bun --env-file=.env.b run index.ts
把--env-file
写到package.json
中,做成脚本命令,然后在终端运行脚本命令:
在package.json
中的scripts
下配置 脚本命令的方式,然后在项目根目录下的终端运行脚本命令:
在 package.json
中的 scripts
配置 start
脚本命令时,指定--env-file
:
{
"name": "quickstart",
"module": "index.ts",
"type": "module",
"bin": {
"my-cli": "dist/index.js"
},
"scripts": {
"clear": "rm -rf dist && echo 'Done!'",
"start": "bun --watch --env-file=.env.abc --env-file=.env.def run index.ts",
"build": "bun build ./index.ts --outdir ./build"
},
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}
然后在项目根目录下的终端运行 bun run start
:
在编辑器中使用有类似.env files support
插件,可以辅助.env文件中环境变量的编写:
在代码编辑器中,以 webstorm 为例,可以下载插件 .env files support
来辅助或规范.env 的编写;
TypeScript中配置环境变量
在 TypeScript 中,来自于
process.env
的所有属性的类型都是string | undefined
为了保持自动推导编译,我们将告诉TypeScript将变量视为非可选的字符串,我们将使用接口合并方式,进行如下配置定义:
declare module "bun" {
interface Env {
AWESOME: string;
}
}
这样我们就能在全局使用 AWESOME
属性。可以将属性添加到 process.env
和 Bun.env
:
process.env.AWESOME; // => string
Bun的部分环境变量说明
Bun也有自身自带的环境变量,我们可以配置它的行为; Bun会自动读取这些环境变量;
这是Bun的部分环境变量的行为说明描述,如下:
环境变量名称 | 描述 |
---|---|
BUN_CONFIG_MAX_HTTP_REQUESTS | 控制获取和bun install 发送的并发HTTP请求的最大数量。默认为256 。如果您遇到速率限制或连接问题,您可以减少这个数字。 |
BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD | 如果BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD=1 ,那么bun --watch 在重新加载时不会清除控制台 |
TMPDIR | 在 bundling或其他操作期间, Bun可能会需要一个目录来存储临时资源。如果未设置,默认为特定于平台的临时目录:Linux上的/tmp ,macOS上的/private/tmp 。 |
... | ... |
Bun的API
Web API
作为包管理器的使用
bun install
bun install
:安装项目的所有依赖项。能使用npm install
的地方,就可以使用bun install
安装依赖。而且bun install
的安装速度更快
, 安装速度几乎是npm的25倍;
运行 bun install
工作过程:
- 安装所有
dependencies
(生产依赖)、devDependencies
(开发依赖)和optionalDependencies
(可选依赖)。默认情况下,Bun将安装peerDependencies
(特定依赖:与主应用的版本有关联); - 在适当的时候运行项目的
{pre|post}install
和{pre|post}prepare
脚本。出于安全原因 , Bun不执行已安装依赖项的生命周期脚本; - 在项目根目录下将项目中的
lockfile
写入到bun.lockb
,(项目根目录下生成bun.lockb
);
-
bun install
的日志控制,有两个标志--verbose
(详细的debug模式,安装情况的日志输出) 和--silent
(静默安装,没有日志输出);# --verbose 是 详细的debug模式,有日志输出 bun install --verbose # --silent 是 静默模式,没有日志输出 bun install --silent
bun install --verbos
: 有详细日志输出:bun install --silent
: 没有日志输出: -
bun install
: Bun默认不会执行被安装package中的scripts中的生命周期钩子,需要告诉Bun允许特定的package的生命周期脚本,请在package.json中将 包 添加到trustedDependencies
与其他
npm
不同,Bun不会为已安装的依赖项执行任意的生命周期脚本,即,Bun默认不会执行被安装package中的scripts中的生命周期钩子,如postinstall
。 执行任意脚本代表着潜在的安全风险。要告诉Bun允许特定的package的生命周期脚本,请在package.json中将 包 添加到trustedDependencies
。
看着很难理解,我们先来学习下npm包的生命周期,各个阶段执行npm生命周期脚本以及含义?
npm script 的生命周期:
preinstall
:在软件包安装开始之前触发。postinstall
:在安装软件包后立即触发。preuninstall
:在卸载软件包之前触发。postuninstall
:卸载软件包后触发。prepare
:在两种情况下触发:在本地安装软件包后(而不是通过注册表)和软件包打包和发布之前(例如,在npm publish
或npm pack
期间)。
npm scripts是写在 package.json中的 scripts; 当该package在被安装之前或之后,被卸载之前或者之后会触发执行对应的生命周期,并执行对应动作:
案例说明:
我们新建个项目,使用 my-trusted-test (这个包已设置了对应生命周期钩子和输出日志),我们使用 npm install
加上命令标志(--foreground-scripts
)来查看脚本执行情况和输出日志,观察下安装过程:
npm install 时 会执行scripts 中的生命周期,这个是非常危险的。这个就意味着可以利用这个特性,在安装依赖包的时候,进行访问用户文件,未授权的资源或者下载安装其他恶意软件,比如进行,例:
cd xx ,rm -rf
等操作;
禁止执行scripts生命周期,可以在 install 的时候,添加标志,例如,npm install --ignore-scripts 你的依赖包
,可以在项目的 .npmrc
中全局配置 ignore-scripts=true
。
-
Bun 支持
package.json
中的workspaces
;{ "name": "my-app", "version": "1.0.0", "workspaces": ["packages/*"], "dependencies": { "preact": "^10.5.13" } }
-
Bun 在
package.json
中,支持npm的overrides
和Yarn的resolutions
,指定元依赖性版本范围的机制,即 依赖项的依赖。{ "name": "my-app", "dependencies": { "foo": "^2.0.0" }, "overrides": { "bar": "~4.4.0" } }
-
Bun install 安装模式, 全局安装:
-g/--global
, 以生产模式安装(即没有devDependencies
或optionalDependencies
):--production
;bun install --global cowsay # or bun install -g cowsay
bun install --production
对于可重现的安装,可以使用
--frozen-lockfile
。这将安装锁文件中指定的每个软件包的确切版本。如果你的package.json
不同意bun.lockb
,Bun将退出并出错。锁文件将不会更新。bun install --frozen-lockfile
进行试运行安装,查看需要的安装的依赖;(实际上不会安装任何东西),需要在 bun init 的项目中使用,需要配置
Scripts
中的install:非npm依赖项的安装,Bun支持从 Git、GitHub 和 本地或者远程,安装依赖项目;
-
bun install
的默认行为可以在bunfig.toml
中配置; 具体的行为配置可以参考 bunfig.toml[install] # whether to install optionalDependencies optional = true # whether to install devDependencies dev = true # whether to install peerDependencies peer = true # equivalent to `--production` flag production = false # equivalent to `--frozen-lockfile` flag frozenLockfile = false # equivalent to `--dry-run` flag dryRun = false # equivalent to `--concurrent-scripts` flag concurrentScripts = 16 # (cpu count or GOMAXPROCS) x2
-
CI/CD的 pipeline 流水线配置,使用官方
oven-sh/setup-bun
操作 bun 的 install,配置CI/CD的流水线;name: bun-types jobs: build: name: build-app runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v4 - name: Install bun uses: oven-sh/setup-bun@v1 - name: Install dependencies run: bun install - name: Build app run: bun run build
bun add
添加指定包(下载指定的依赖包)可以指定依赖包,版本范围,可以添加为dev依赖项,可选依赖等
- 下载添加指定的依赖包
bun add preact
- 指定版本,版本范围或者指定标识:
bun add zod@3.20.0 bun add zod@^3.0.0 bun add zod@latest
--dev
,-d
,-D
,--development
: 将依赖包添加为dev依赖项(package.json下的 "devDependencies" 项)
:增加
--development
, 或-d
或--dev
或-D
;bun add --dev @types/react bun add -d @types/react
--optional
: 将依赖包添加为可选依赖项(package.json下的 "optionalDependencies" 项)
:bun add --optional lodash
--exact
,-E
: 添加固定版本的依赖包,bun add react --exact bun add react -E
{ "dependencies": { // without --exact 添加不固定的依赖包 "react": "^18.2.0", // this matches >= 18.2.0 < 19.0.0 // with --exact 添加固定版本的依赖包 "react": "18.2.0" // this matches only 18.2.0 exactly } }
--global
,-g
: 安装全局依赖包,这不会修改你当前项目的package.json
。这通常用于安装命令行工具。bun add --global cowsay cowsay "Bun!"
- bun add 也可以 从 git仓库添加依赖包:
bun add git@github.com:moment/moment.git
- bun add的时候不会执行任意包的 Scripts的生命周期,要执行指定依赖包的生命周期,需要在 package.json 中将依赖包添加到
trustedDependencies
;
例: 要添加 my-trusted-test并执行该依赖包的Scripts生命周期,需要在trustedDependencies
中添加该依赖包:{ "name": "my-app", "version": "1.0.0", "trustedDependencies": ["my-trusted-test"] }
bun remove
删除移除依赖包
bun remove ts-node
bun update
更新依赖包(依赖项)
- 将所有依赖项更新到最新版本;
bun update
- 将指定的依赖包更新到最新版本;
bun update [依赖包名称]
--latest
: 要更新到最新版本,无论它是否与当前版本范围兼容,就使用--latest
标志:
例:我们现在的bun update --latest
package.json
是如下的:
使用{ "dependencies": { "react": "^17.0.2" } }
bun update
将更新到与17.x
匹配的版本。
使用bun update --latest
将更新到与18.x
或更高版本匹配的版本。
bun pm
bun pm
提供了一些命令组,它是实用的查看命令程序,用于查看Bun的软件包相关的命令;
bun pm bin
: 查看本地项目的bin
目录路径,要在本地项目的根目录下运行;bun pm bin -g
: 查看全局bin
目录的路径;bun pm ls
: 查看当前项目中已安装的依赖项及其它们的解析版本,不包括其他依赖项;bun pm ls --all
: 查看所有已安装的依赖项,包含 nth-order 的dependencies;bun pm cache
: 查看 Bun 的全局模块缓存的路径;要在当前项目中运行;bun pm cache rm
: 清除 Bun 的全局模块缓存;要在当前项目中运行;当然了。全局缓存,也可以通过配置文件
bunfig.toml
,进行配置它的行为方式;一般从下载源下载的所有软件包都会存储在~/.bun/install/cache
的全局缓存中;
也可以在全局配置中
bunfig.toml
配置缓存行为方式:
bun link
bun link
的作用 和npm link
类似,可以 在本地目录中使用bun link
将当前包 注册为 "可链接" 包,就是将本地包注册做成 软链接(快捷方式),做成 本地全局包,这样可以在本地的其他项目中,使用bun link xxx
,将这个包链接到本地的其他项目, 也就是说在本地的其他项目的node_modules
中创建了一个软链接,链接到本地这个bun link的可链接的包。这样就可以很方便的本地调试一些封装的库sdk等;
简单演示下 bun link
的作用,示例:
①.首先我们使用bun init
创建名称为cool-pkg
的项目;然后在index.ts
中导出一个求和函数;
②.在项目
cool-pkg
根目录下,运行bun link
将当前项目注册成“可链接”包
;
③.现在可以使用
bun link cool-pkg
将这个包,链接到其他项目中(例:my-app项目);这会在其他项目中的node_modules
目录中创建一个符号链接,执行本地目录。
④.
可以直接在其他项目中(my-app),使用或者引入 可链接包(cool-pkg包)中导出的函数
;
⑤.在使用可链接包
bun link cool-pkg
时,也可以通过添加 --save
标志,将cool-pkg
添加到应用程序的package.json
的dependencies
字段中,该link
符号告诉Bun从注册的本地目录加载,而不是从npm
安装;
WorkSpaces(工作区)
Bun支持
package.json
中的workspaces
。workspaces
使得将复杂的软件作为由几个的独立的包,组成的单个包来开发变得容易;基于workspaces的特性,被常用于构建monorepo类型(单体仓库)的项目;
workspaces的几个优点:
- 代码可以分为逻辑部分。如果一个包依赖于另一包,你可以简单地将其作为依赖项添加到
package.json
中。如果软件包b
依赖于a
,bun install
会将你的本地包package/a
目录安装到node_modules
而不是从npm下载源下载。 - 依赖项可以重复使用。如果
a
和b
共享一个共同的依赖项,它将被带到根node_modules
目录。这就大大的减少了冗余磁盘的使用。并最大限度的减少了与同时安装多个版本的软件包相关的 “依赖地狱”问题。 - 在多个软件包中运行脚本。你可以使用
--filter
标志,在workspace的多个软件包中轻松运行package.json
脚本。
常见的单个包单个仓库(monorepo)的标准工作结构:
在根目录的
package.json
中"workspaces"
键用于指示哪些子目录应该被视为monorepo单体仓库中的package或workspaces。传统上,将所有workspaces
都放在一个名为packages
目录中。
每个workspaces都有自己的package.json,在monorepo中引用其他包时,需要使用
workspace:*
作为package.json中的版本字段。
Scripts生命周期
Bun 默认不执行任意的Scripts生命周期。
npm
上的软件包可以在其package.json
中定义生命周期脚本。一些最常见的在下面,但还有很多其他的。
preinstall
:在安装软件包之前运行postinstall
:在安装软件包后运行preuninstall
:在卸载软件包之前运行prepublishOnly
:在软件包发布之前运行
这些脚本是软件包管理器在适当时间读取和执行的任意shell命令。但执行任意脚本代表着潜在的安全风险,因此,与其他npm
客户端不同,Bun默认不执行任意生命周期脚本。
trustedDependencies
Bun使用“默认安全”方法,而不是执行任意脚本。您可以将某些软件包添加到允许列表中,Bun将为这些软件包执行生命周期脚本。要告诉Bun允许特定软件包的生命周期脚本,请将软件包名称添加到
package.json 的trustedDependencies
数组中。
--ignore-scripts
要禁用所有软件包的生命周期脚本,请使用
--ignore-scripts
标志。
bun install --ignore-scripts
LockFile锁文件
运行
bun install
将创建一个名为bun.lockb
的二进制锁文件(bun.lockb
);
为什么bun的锁文件是二进制?
与 npm, yarn 等包管理工具不同,bun的锁文件是二进制的,为啥是二进制的,主要是基于性能考虑,Bun的锁文件保存和加载速度非常快,并且比通常在锁文件内保存的数据要多得多。
bun install 的 范围(Scopes) 和 注册表下载源(registry)
bun 默认的依赖下载范围,注册源下载源配置
- Bun默认的下载源注册表是:
registry.npmjs.org
。这个也可以在bunfig.toml
中配置:要配置特定组织范围的私有注册表:
.npmrc
: Bun目前不读取.npmrc
文件。对于私有的注册表,需要在bunfig.toml
中配置;
Bundler(构建打包)
Bun的快速原生构建现在处于实验阶段。它可以通过这两种方式:1.
bun build
的cli命令方式;2.Bun.build()
的JavaScriptAPI方式来使用的。目的是配置Bun构建的行为方式;类似于 webpack 和 vite的项目配置文件(webpack.config.js, vite.config.ts
)的配置方式,只不过bun还可以使用JavaScriptAPI的方式进行配置;
Bun的构建打包更快,以下是Bun构建和其他构建的的性能速度对比:
注意:Bun的构建打包(bunlder)不打算取代tsc
进行类型检查或者生成类型声明的。即Bun的构建的时候不会进行ts的类型检查的。
JavaScript API方式
使用JavaScript的API方式进行配置Bun的构建行为;一般是在Bun项目的入口文件(例:index.ts)中进行配置;当然了你可以在
entrypoints
指定要构建的文件;
bun build 命令方式
使用终端命令
bun build
,命令格式如:bun build ./index.tsx --outdir ./out
--wach
: 监听观察模式,指定要构建打包的文件有变化,就会实时变化输出的文件内容;命令格式如:bun build ./index.tsx --outdir ./out --watch
;
构建打包中常用的API说明
-
entrypoints
: 必需参数,应用程序的入口,打包的起点;
JavaScriptAPI方式的使用:const result = await Bun.build({ entrypoints: ["./index.ts"], }); // => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }
bun build命令方式的使用:
bun build --entrypoints ./index.ts
-
outdir
: 构建打包后的输出文件的目录; JavaScriptAPI方式的使用:const result = await Bun.build({ entrypoints: ['./index.ts'], outdir: './out' }); // => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }
bun build命令方式的使用:
bun build --entrypoints ./index.ts --outdir ./out
设置了outdir
时,BuildArtifact
中的path
属性,将是 绝对路径。 -
target
: 构建打包后的预期执行环境;构建打包后的文件将运行在哪个环境;Bun对不同环境会有不同的解析规则和优化; JavaScriptAPI方式的使用:await Bun.build({ entrypoints: ['./index.ts'], outdir: './out', target: 'browser', // default })
bun build命令方式的使用:
bun build --entrypoints ./index.ts --outdir ./out --target browser
执行环境 描述 browser
默认。 用于生成旨在由浏览器执行的包。在解决导入问题时,优先考虑 "browser"
导出条件。导入任何内置模块,likenodenode:events
或node:path
将有效,但调用一些函数(如fs.readFile
)将不起作用。bun
用于生成打算由Bun运行时运行的包。在许多情况下,没有必要捆绑服务器端代码;您可以直接执行源代码,无需修改。然而,捆绑服务器代码可以减少启动时间并提高运行性能。 如果任何入口点包含一个Bun shebang( #!/usr/bin/env bun
)捆绑程序将默认为target: "bun"
而不是"browser"
node
用于生成打算由Node.js运行的包。在解决导入时优先考虑 "node"
导出条件,并输出.mjs
。将来,这将自动填充Bun
全局和其他内置bun:*
模块,尽管这尚未实现。
其他构建打包行为相关的配置可查看 构建打包相关的API配置
bunx工具
bunx 是
bun x
命令的 别名,bunx的cli脚手架工具,将从你的bun
自动安装运行。对于本地安装,bunx 比 npx 更快!还记得吗?node 有个 npx ;对于本地安装的包bunx
比npx
约快100倍;
-
使用
bunx
从npm自动安装并运行软件包。它相当于npx
或yarn dlx
;bunx cowsay "Hello world!"
-
软件包可以在其
package.json
的"bin"
字段中声明可执行文件。这些被称为软件包可执行文件或软件包二进制文件。{ // ... other fields "name": "my-cli", "bin": { "my-cli": "dist/index.js" } }
这些可执行文件通常是标有shebang行的普通JavaScript文件,以指示应该使用哪个程序来执行它们。以下文件表明它应该与
node
一起执行。
这些可执行文件可以用
bunx
运行,与
npx
,bunx
将首先检查本地安装的软件包,然后回退到从npm
自动安装软件包。已安装的软件包将存储在Bun的全局缓存中,以备将来使用。 -
传递参数和标识;
要将其他命令行标志和参数传递给可执行文件,请将它们放在可执行文件名称之后。
-
Shebangs
默认情况下,Bun尊重shebangs。如果可执行文件被标记为#!/usr/bin/env node
,Bun将启动一个node
进程来执行文件。然而,在某些情况下,使用Bun的运行时运行可执行文件可能是可取的,即使可执行文件指示相反。要做到这一点,请包括--bun
标志。--bun
标志必须出现在可执行名称之前。名称后出现的标志被传递到可执行文件。要强制面包始终与脚本一起使用,请使用shebang。
Bun的内置API使用
Bun和Node.js类似,基本的API大部分兼容,Bun自己内部也实现了一些常用的API,例:创建 HTTP服务器,WebSockets, 文件I/O等;具体如何使用请查看文档;