Bun 的四大身份
理解 Bun 的关键在于:它不只是"另一个 Node.js",而是一个完整工具链,由四个独立的子系统组成:
-
bun run
JavaScript/TypeScript 运行时,基于 JavaScriptCore,Node.js API 兼容层。直接执行
.ts、.tsx、.jsx无需配置。 - bun install 包管理器,兼容 npm 生态,使用全局缓存(symlink 策略),安装速度比 npm 快 10-30 倍,比 pnpm 快 3-5 倍。
- bun build 打包器,基于 Zig 编写的极速 bundler,支持 tree-shaking、代码分割、目标平台(browser/node/bun)。
- bun test Jest 兼容的测试运行器,速度比 Jest 快 10-50 倍,详见第9章。
bun install — 极速包管理
工作原理
Bun 的包管理之所以快,核心在于全局内容寻址缓存:
# Bun 的全局缓存目录
~/.bun/install/cache/
# 当你 install 一个包:
# 1. 检查缓存是否已有该版本(按 hash 寻址)
# 2. 缓存命中:直接 hardlink 或 symlink 到 node_modules
# 3. 缓存未命中:下载、提取、写入缓存,然后 link
# 4. 全程并发执行,无依次下载的串行等待
常用命令
# 安装 package.json 中所有依赖
bun install
# 添加依赖
bun add hono zod
bun add -d typescript @types/bun # 开发依赖
bun add -g http-server # 全局安装
# 删除依赖
bun remove lodash
# 更新依赖
bun update
# 运行 package.json scripts
bun run dev
bun run build
bun run test
bun.lock 格式
Bun 1.2+ 引入了二进制格式的 bun.lock 文件,取代了之前的 bun.lockb(也是二进制,但现在改为文本):
# bun.lock 是人类可读的文本格式(类似 yarn.lock)
# 应该提交到 git,确保团队和 CI 使用完全一致的依赖版本
# 与 npm/yarn 的互操作
# Bun 会读取 package-lock.json / yarn.lock 进行兼容
bun install --frozen-lockfile # CI 环境:锁定安装,不更新
workspaces 支持:Bun 完全支持 npm workspaces(monorepo),在 package.json 中定义 "workspaces": ["packages/*"] 即可,bun install 自动处理所有子包的依赖提升。
bun build — 内置打包器
// build.ts — 构建脚本示例
const result = await Bun.build({
entrypoints: ['./src/index.ts'],
outdir: './dist',
target: 'bun', // 或 'node' | 'browser'
format: 'esm',
minify: true,
splitting: true, // 代码分割
sourcemap: 'linked',
external: ['pg', 'redis'], // 不打包这些模块
});
if (!result.success) {
console.error(result.logs);
process.exit(1);
}
console.log(`打包完成:${result.outputs.length} 个文件`);
Bun Shell — 内置 Shell 脚本
Bun Shell($\`command\` 语法)是 Bun 1.0 最惊艳的特性之一,让你在 TypeScript 中写 Shell 脚本,跨平台(包括 Windows):
import { $ } from 'bun';
// 基础用法
await $`echo Hello, World!`;
// 获取输出
const result = await $`ls -la`.text();
console.log(result);
// 插值(自动转义,防注入)
const filename = 'my file.txt';
await $`cat ${filename}`; // 安全:会转义空格
// 管道
const lines = await $`cat package.json | grep name`.lines();
// 错误处理
const output = await $`git status --short`.quiet().nothrow();
if (output.exitCode !== 0) {
console.log('不在 git 仓库中');
}
// 环境变量
await $`echo $HOME`.env({ HOME: '/custom/home' });
// 实际应用:构建脚本
async function deploy() {
console.log('开始构建...');
await $`bun run build`;
await $`docker build -t my-app:latest .`;
await $`docker push my-app:latest`;
console.log('部署完成 ✓');
}
deploy();
告别 shelljs:Bun Shell 是 shelljs、execa 等包的内置替代品。最大优势是跨平台——同样的脚本在 macOS、Linux、Windows 上都能运行,不需要 WSL。
内置 SQLite
Bun 内置了高性能的 SQLite 支持(通过 bun:sqlite),无需安装任何 npm 包,性能比 better-sqlite3 快约 3 倍:
import { Database } from 'bun:sqlite';
// 打开/创建数据库
const db = new Database('mydb.sqlite');
// 内存数据库:new Database(':memory:')
// 建表
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 预编译语句(推荐,防 SQL 注入)
const insertUser = db.prepare(`
INSERT INTO users (name, email) VALUES ($name, $email)
`);
// 插入
insertUser.run({ $name: '张三', $email: 'zhang@example.com' });
// 查询单行
const getUser = db.prepare('SELECT * FROM users WHERE id = $id');
const user = getUser.get({ $id: 1 });
// 查询多行
const getAllUsers = db.prepare('SELECT * FROM users ORDER BY created_at DESC');
const users = getAllUsers.all();
// 事务(性能关键:批量操作用事务包裹,速度提升数十倍)
const insertMany = db.transaction((users: Array<{name: string, email: string}>) => {
for (const user of users) {
insertUser.run({ $name: user.name, $email: user.email });
}
});
insertMany.immediate([
{ name: '李四', email: 'li@example.com' },
{ name: '王五', email: 'wang@example.com' },
]);
// 关闭连接
db.close();
何时用内置 SQLite vs Prisma:内置 SQLite 适合本地工具、测试数据、中小型应用(用户量 < 10万)。大型应用推荐 PostgreSQL + Prisma ORM(见第5章)。SQLite 本身没有问题,但缺乏并发写入能力,不适合高写入负载。
文件读写 API
Bun 提供了比 Node.js fs 模块更简洁的文件 API:
import fs from 'node:fs/promises';
// 读取文件
const text = await fs.readFile(
'./data.json', 'utf8'
);
// 写入文件
await fs.writeFile(
'./output.txt',
'Hello World',
'utf8'
);
// 追加内容
await fs.appendFile(
'./log.txt', 'new line\n'
);
// Bun.file() 返回 BunFile 对象(惰性)
const file = Bun.file('./data.json');
// 读取为文本
const text = await file.text();
// 读取为 JSON(自动解析)
const json = await file.json();
// 读取为 ArrayBuffer
const buf = await file.arrayBuffer();
// 写入(极速,使用系统调用优化)
await Bun.write(
'./output.txt', 'Hello World'
);
BunFile 的惰性求值
Bun.file() 不会立即读取文件,只是创建一个引用。只有调用 .text()、.json() 等方法才真正读取——这使得传递文件引用非常高效:
const file = Bun.file('./large-file.bin');
console.log(file.size); // 文件大小(字节),不读取内容
console.log(file.type); // MIME 类型(自动推断): "application/octet-stream"
console.log(file.name); // 文件路径
console.log(await file.exists()); // 是否存在
// 将文件作为 HTTP 响应体(零拷贝)
const server = Bun.serve({
port: 3000,
fetch(req) {
// Bun 会使用 sendfile() 系统调用,零拷贝传输
return new Response(Bun.file('./index.html'));
}
});
Bun.serve — 内置 HTTP 服务器
Bun 内置了基于 uWebSockets.js 的超高性能 HTTP 服务器,无需任何框架即可使用:
import { type Server } from 'bun';
const server = Bun.serve({
port: 3000,
hostname: '0.0.0.0',
// 每个请求调用 fetch
async fetch(req: Request, server: Server) {
const url = new URL(req.url);
if (url.pathname === '/') {
return new Response('Hello from Bun!');
}
if (url.pathname === '/json') {
return Response.json({ message: 'Hello', time: Date.now() });
}
// 读取请求体
if (req.method === 'POST' && url.pathname === '/echo') {
const body = await req.json();
return Response.json(body);
}
return new Response('Not Found', { status: 404 });
},
// 错误处理
error(err) {
return new Response(`Error: ${err.message}`, { status: 500 });
}
});
console.log(`服务器运行在 http://localhost:${server.port}`);
环境变量与 .env 支持
Bun 原生支持 .env 文件,无需 dotenv 包:
# .env 文件(自动加载)
DATABASE_URL=postgresql://localhost:5432/mydb
JWT_SECRET=your-secret-key
PORT=3000
NODE_ENV=development
// TypeScript 中直接访问
const port = Number(process.env.PORT ?? '3000');
const dbUrl = process.env.DATABASE_URL!;
// Bun 也支持类型安全的环境变量(通过 TypeScript 声明)
// 在 src/types/env.d.ts 中:
declare namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
JWT_SECRET: string;
PORT?: string;
NODE_ENV: 'development' | 'production' | 'test';
}
}
优先级:Bun 加载 .env 的优先级为:.env.local > .env.[NODE_ENV] > .env。切记将 .env.local 加入 .gitignore,.env 只存放公开的默认值。
Node.js 兼容性
Bun 目标是实现完整的 Node.js API 兼容,2024 年的兼容率已超过 95%:
| Node.js 模块 | Bun 兼容状态 |
|---|---|
node:fs, node:path | ✅ 完全兼容 |
node:http, node:https | ✅ 完全兼容 |
node:crypto | ✅ 完全兼容 |
node:stream | ✅ 基本兼容 |
node:worker_threads | ✅ 支持 |
node:child_process | ✅ 支持 |
| Native Addons (.node) | ⚠️ 部分支持(Node-API/napi) |