概述
本文是笔者的系列博文 《Bun技术评估》 中的第十五篇。
在本文的内容中,笔者主要想要来探讨一下Bun中应用程序项目(Bun Project)相关方面的问题。
Bun Project
我们在前面的内容已经了解到,Bun是一个非常灵活的,对于开发者十分友好和容易使用的应用开发平台和环境。理论上而言,任何JS/TS文件,都可以直接使用Bun来执行,但考虑到更好的开发协作和流程管理的需求,Bun仍然引入了和Nodejs一样的项目管理和相关的操作。
和nodejs一样,我们可以使用一个普通的操作系统文件夹,来组织和应用程序原始代码相关的文件,配置文件、库文件和媒体资产文件,来构成一个完整的应用程序项目。很多框架库还提供了脚手架的功能,可以快速构成一个具有基本结构的框架项目,这些都大大方便了我们初始化开发应用程序的工作。
一般而言,我们在bun中完全从零开始,创建一个开发项目的基本操作的过程如下:
- 创建一个文件夹(项目文件夹),通常使用mkdir命令完成
- 进入文件夹(设置当前工作环境),通常使用cd命令
- 初始化Bun项目,通常使用init命令
- 检查配置文件夹结构
- 检查并确认配置信息(package.json)
- 进行后续开发工作
- 相关依赖包管理...
这一系列的实际操作示例如下:
j
```shell
// 创建项目文件夹
PS C:\Work\Dev> mkdir bproject
Directory: C:\Work\Dev
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2025-7-17 13:02 bproject
// 进入项目文件夹
PS C:\Work\Dev> cd bproject
// 项目初始化
PS C:\Work\Dev\bproject> bun init -y
+ .gitignore
+ index.ts
+ tsconfig.json (for editor autocomplete)
+ README.md
To get started, run:
bun run index.ts
// 文件夹结构
PS C:\Work\Dev\bproject> ls
Directory: C:\Work\Dev\bproject
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2025-7-17 13:03 node_modules
-a--- 2025-7-17 13:03 388 .gitignore
-a--- 2025-7-17 13:03 1997 bun.lock
-a--- 2025-7-17 13:03 30 index.ts
-a--- 2025-7-17 13:03 195 package.json
-a--- 2025-7-17 13:03 223 README.md
-a--- 2025-7-17 13:03 713 tsconfig.json
PS C:\Work\Dev\bproject> ls node_modules
Directory: C:\Work\Dev\bproject\node_modules
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2025-7-21 10:37 .bin
d---- 2025-7-21 10:37 @types
d---- 2025-7-21 10:37 bun-types
d---- 2025-7-21 10:37 csstype
d---- 2025-7-21 10:37 typescript
d---- 2025-7-21 10:37 undici-types
// package.json 内容
PS C:\Work\Dev\bproject> cat package.json
{
"name": "bproject",
"module": "index.ts",
"type": "module",
"private": true,
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5"
}
}
// 测试执行
PS C:\Work\Dev\bproject> bun .
Hello via Bun!
至此,我们就完全从零开始,创建了一个最基本的bun项目,并可以继续开展后续的应用开发工作了。
Init
上面的操作步骤中,我们应该可以看到,将一个普通的文件夹,转换为bun项目的核心,就是bun init命令了。这里使用了-y标签,让它安装默认配置进行设置。这个命令基本上创建了以下一些文件和内容:
- package.json
这个和nodejs一样,都是项目配置信息文件。后面会讨论文件内容和组成。
- node_modules文件夹
实际上在初始化的时候,bun会安装一些基本的库,如@type、bun-types、csstype、typescript、undici-types等等。这个操作,笔者理解主要是一个兼容性的操作。
- 默认的程序入口文件index.ts
内容就只有一行代码: console.log("Hello via Bun!")。但这个文件如果可以正常执行,表明项目和相关环境配置应该是有效的。
- readme.md文件
开发者可以编写项目相关信息,让后续开发者可以有机会了解到项目相关信息。这是一个比较好的操作实践。
- tsconfig.json
ts程序相关配置。bun支持ts,所以有一套默认推荐的配置方式。
- bun.lock
bun依赖包锁定,这个笔者会在另外一篇包管理相关的文件中探讨。
- .gitignore
git排除配置文件(是有内容的)。但有趣的是,bun并没有直接初始化git配置。
执行bun init --help,可以看到一些初始化的选项如下:
js
PS C:\Work\Dev\btest> bun init --help
Usage: bun init [flags] [<folder>]
Initialize a Bun project in the current directory.
Creates a package.json, tsconfig.json, and bunfig.toml if they don't exist.
Flags:
--help Print this menu
-y, --yes Accept all default options
-m, --minimal Only initialize type definitions
-r, --react Initialize a React project
--react=tailwind Initialize a React project with TailwindCSS
--react=shadcn Initialize a React project with @shadcn/ui and TailwindCSS
选项并不复杂,里面有一些和前端开发相关的选项,特别是React初始化相关的内容。笔者注意专注于Web开发,就不再展开讨论了。有兴趣的读者可以自行研究。
create
bun的一个重要的特性,就是支持前端开发(重点是React)。所以,bun提供了create指令,来提供更强大的项目初始化能力,简单而言,就是可以基于一个框架和模板,来创建bun项目(主要是前端项目)。这个命令非常灵活和强大,可用于从React组件、npm包、GitHub存储库或本地模板创建新项目。
下面是几个简单的示例:
js
// 基于React组件
bun create ./MyComponent.jsx
// 基于npm
bun create remix
// 基于github
bun create github.com/<user>/<repo> mydir
// 本地模板,需要修改模板项目配置
{
"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!'"
}
}
基于前面已经表述的理由,这里也不再展开,读者只需要了解到有这个特性即可。
除了bun内置的init和create命令之外,有一些开发框架,也提供了类似的功能,就是所谓的脚手架,它们可以创建基于这个框架的级别的应用程序的架构,包括了基本的目录结构和相关的安装依赖。这样可以让开发者可以不用从零开始,而且可以基于一些最佳实践,快速入门并且提高开发效率。
package.json
package.json是bun的基础项目配置文件,这个设定基本上和nodejs相同。但如果深究,还是会发现有一些细节上的差异。
- type
默认就是module。因为bun建议和默认使用ts开发。
- module
程序入口文件(一般为index.ts),在Nodejs中,一般是main项目。
-
有初始化的dependence项目
-
没有版本信息?
-
支持scipts,但没有默认项目。
-
没有keywords、author、license、description等辅助项目信息(可能建议使用README文件)
笔者在bun技术文档中,没有查到规范和完整的package.json定义信息。只能暂时认为在其他项目上,和nodejs的方式是一致的。
bunfig.toml
可能是考虑到bun自身的一些特性,并且不希望影响到nodejs项目的配置内容和兼容性。bun使用了一个独立的配置文件,来控制bun项目相关的行为,这就是.bunfig.toml配置文件。这里需要理解,这个文件不是必须的,而且它仅用于配置bun特定的东西,所以逻辑上它和package.json并不冲突。
.bonfig.toml有本地和全局两种配置,本地配置就是项目文件夹,全局配置文件在以下路径之一:
$HOME/.bunfig.toml
$XDG_CONFIG_HOME/.bunfig.toml
如果同时检测到全局和局部,则结果是浅层合并的,局部覆盖全局。开发者还可以使用CLI标记强行指定特定的配置或者对配置项进行覆盖(命令行参数优先级最高)。
.bunfig.toml基于toml语法,就是分区域,键=值的方式,使用#进行注释。
常见的bunfig的区域包括:
- test 测试控制
- install 安装配置控制
- run 执行控制
- runtime 运行时(顶层)
笔者觉得其中比较有趣和重要的配置项目包括:
- preload 预加载脚本,常用于环境和依赖准备
简单示例:
js
# scripts to run before `bun run`-ing a file or script
# register plugins by adding them to this list
preload = ["./preload.ts"]
-
smol 小内存模式,可能会稍微影响性能
-
logLevel 控制日志级别
js
logLevel = "debug" # "debug" | "warn" | "error"
- loader 加载器
笔者理解,loader就是一个文件扩展名的映射器,它可以控制bun如何加载一个无法识别扩展名的文件。例如:
js
[loader]
# when a .bagel file is imported, treat it like a tsx file
".bagel" = "tsx"
bun可以识别和处理的文件类型如下:jsx、js、ts、tsx、css、file、json、toml、wasm、napi、base64、dataurl、text等等。
- telemetry 遥测
该字段允许启用/禁用分析记录,来帮助Bun记录执行时间(因此我们可以用数据回答"Bun 是否变得更快?)。遥测内容正文大小约为60字节,非常精简。默认情况下,telemetry遥测已启用。
- test.converage 开启/关闭测试覆盖
js
[test]
coverage = false
-
install.auto 控制自动安装,可选项目包括auto、force、disable、fallback等等。
-
install.registry
可以设置安装仓库的镜像,在某些环境中非常重要。
js
[install]
# set default registry as a string
registry = "https://registry.npmjs.org"
# set a token
registry = { url = "https://registry.npmjs.org", token = "123456" }
# set a username/password
registry = "https://username:password@registry.npmjs.org"
- run.shell
控制使用系统shell或者bun shell:
js
[run]
# default outside of Windows, "system" or "bun"
shell = "system"
-
run.bun 控制是否使用bun执行原有nodejs执行的脚本
-
run.slient 控制是否以静默模式运行
完整的配置项目,读者可以参考下面的技术文档原始链接:
script
在package.json中,可以选择配置一些script项目,来简化和规范化应用开发工作。
下面是一些简单的示例:
package.json
{
// ... other fields
"scripts": {
"clean": "rm -rf dist && echo 'Done.'",
"dev": "bun server.ts"
}
}
这里定义了两个执行脚本: clean、dev,分别对应命令行指令。执行时,就可以统一的使用bun run命令:
js
// 查看可选脚本
bun run
quickstart scripts:
bun run clean
rm -rf dist && echo 'Done.'
bun run dev
bun server.ts
2 scripts
// 执行脚本
bun run clean
$ rm -rf dist && echo 'Done.'
Cleaning...
Done.
实际上,bun run是一个非常强大的命令,它不仅可以执行快速脚本,也可以执行代码文件,而且还有很多选项,但那就是另外一个主题了。
其他项目结构
前面我们已经了解到一个bun开发项目的基本构成。但这个构成,没有任何框架和业务方面的内容。因为这些内容主要基于一些最佳实践和经验,并没有一个严格的规范和标准,开发者需要根据自己项目的情况,自行选择合适的项目组织方式。
这里有一些简单的命名和使用建议:
- controllers: web项目的控制器文件,简单的项目可以直接用route文件
- models: 模型文件
- views: 视图文件,当然在前后端分离的应用中,使用较少
- assets: 存储资产文件,如需要用到的模板文件,图片文件,文本内容等等
- lib: 库,一般是自有库,外部和第三方库优先考虑npm
- helpers: 工具类,一般是当前项目相关的
- _conf,_const: 配置信息和常数/字典等等
- 工作文件夹,如temp、 work、 data等: 优先使用链接方式管理
- 配置信息,优先使用env(bun使用env更方便)
WorkSpace
先说明一下,这部分的内容,笔者的经验也比较有限,现在也没有太多实际操作的机会,所以主要是理论和感觉的探讨,同时觉得值得尝试一下。
笔者理解,workspace就是工作空间,它是一种更有效的多个相关开发项目的组织和管理方式,用于支持更复杂的开发项目。比如一个完整的Web应用项目,可能会涉及到前端项目、后端的API、数据服务和管理服务等多个相对独立,而又有一些关联关系的应用,就可以使用workspace方式来进行管理。这种方式的好处是:
- 代码可以拆分为逻辑部分(模块化)
首先模块内部相对独立,就好像独立的项目一样。另外如果一个项目依赖于另一个项目,只需将其添加为依赖项(而非直接引用)。这样就可以基于本地目录安装配置,而无需npm仓库。
- 统一一致的包管理
在工作空间就可以方便的管理包的安装和配置,例如:
js
# Install dependencies for all workspaces starting with `pkg-` except for `pkg-c`
bun install --filter "pkg-*" --filter "!pkg-c"
# Paths can also be used. This is equivalent to the command above.
bun install --filter "./packages/pkg-*" --filter "!pkg-c" # or --filter "!./packages/pkg-c"
- 可以删除重复项
工作空间中,不同的包使用的共享依赖项目,将会被提升到根目录中。这将显著减少磁盘的使用,并最大限度地减少了与同时安装多个版本的包相关的"依赖地狱"问题。
- 在多个包中运行脚本
在工作空间根中,可以使用 --filter 标志轻松运行工作区中多个包中的脚本。方便统一的开发和测试体验。
Bun支持workspace这种项目组织的形式。它主要通过结构化的项目文件夹组织和配套的配置文件来实现。下面是一个简单的示例:
js
// 工作空间结构
tree
<root>
├── README.md
├── bun.lock
├── package.json
├── tsconfig.json
└── packages
├── pkg-a
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── pkg-b
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
└── pkg-c
├── index.ts
├── package.json
└── tsconfig.json
// 工作空间配置信息
{
"name": "my-project",
"version": "1.0.0",
"workspaces": ["packages/*"],
"devDependencies": {
"example-package-in-monorepo": "workspace:*"
}
}
// 包A 配置信息
{
"name": "pkg-a",
"version": "1.0.0",
"dependencies": {
"pkg-b": "workspace:*"
}
}
从这些配置方式和信息中可以看到,bun主要是通过workspaces配置项目(支持多个名字空间),和简化的包声明方式来实现工作空间中,项目和依赖的管理的。
小结
本文探讨了bun开发项目相关的内容,包括如何初始化项目,package.json文件格式和内容,bun执行脚本,bunfig.toml文件的作用和配置项目,工作空间等等。