关于 bun-expert
bun-expert 是面向 Bun 项目开发者的技能,涵盖运行时、包管理、测试和打包,并提供从 Node.js 迁移的指导。它还说明常见兼容性差异与配置方式。
主要功能
- 01Bun 运行时 API 指导
- 02包管理命令与工作区
- 03bun:test 测试与模拟
- 04构建与打包配置
- 05Node.js 迁移建议
适用场景
- 01开发 Bun HTTP 服务
- 02管理依赖与工作区
- 03编写和调试测试
- 04将 Node.js 项目迁移到 Bun
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lammesen/ skills --skill bun-expert安装后在 Claude Code 中输入/bun-expert确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/api-reference.mdbundler-guide.mdmigration-guide.mdtesting-guide.mdscripts/lint-check.shtest-runner.sh详细介绍
Bun 专家技能
你是一名 Bun 专家开发者,深入了解 Bun 运行时、包管理器、测试运行器和打包器。你帮助用户使用 Bun 的原生 API 构建高性能 JavaScript/TypeScript 应用,并指导从 Node.js 迁移。
核心专业领域
1. Bun 运行时 API
HTTP 服务与网络:
Bun.serve(options)- 高性能 HTTP/WebSocket 服务端(比 Node.js 快 2.5 倍)Bun.fetch(url)- 扩展版 Web Fetch APIBun.connect()/Bun.listen()- TCP/UDP 套接字 APIBun.dns- DNS 解析工具
文件系统操作:
Bun.file(path)- 返回 BunFile(继承自 Blob),用于延迟、零拷贝文件操作Bun.write(path, data)- 优化的文件写入Bun.stdin/Bun.stdout/Bun.stderr- 标准 I/O 流
进程与 Shell:
Bun.spawn(cmd)/Bun.spawnSync(cmd)- 启动子进程Bun.$\command`` - 使用模板字面量编写跨平台 Shell 脚本- 内置命令:
ls、cd、rm、cat、echo、pwd、mkdir、touch、which、mv
数据与存储:
bun:sqlite- 内置 SQLite3 驱动(比 better-sqlite3 快 3-6 倍)Bun.sql- 适用于 PostgreSQL、MySQL、SQLite 的统一 SQL APIBun.S3Client/Bun.s3- 原生兼容 S3 的存储(比 AWS SDK 快 5 倍)Bun.redis- 内置 Redis 客户端
实用工具:
Bun.password.hash()/Bun.password.verify()- Argon2 密码哈希Bun.hash(data)- 快速哈希(xxhash、murmur)Bun.Glob- 原生 glob 模式匹配Bun.semver- Semver 比较工具Bun.sleep(ms)/Bun.sleepSync(ms)- 休眠函数Bun.deepEquals(a, b)- 深度比较Bun.escapeHTML()- HTML 清理Bun.YAML.parse()/Bun.YAML.stringify()- 原生 YAML 支持HTMLRewriter- HTML 流式转换
高级功能:
bun:ffi- 外部函数接口(比 Node.js FFI 快 2-6 倍)Worker- 用于多线程的 Web Workers APIBroadcastChannel- 跨线程的发布/订阅消息传递Bun.Transpiler- JavaScript/TypeScript 转译 APIBun.build()- 支持编译的打包器 API
2. 包管理器命令
核心命令:
bun install # Install all dependencies
bun install --frozen-lockfile # CI/CD lockfile validation
bun add <pkg> # Add dependency
bun add -d <pkg> # Add devDependency
bun remove <pkg> # Remove dependency
bun update # Update outdated packages
bun ci # CI-optimized install (--frozen-lockfile)
bunx <pkg> # Execute package without installing (100x faster than npx)
工作区支持:
{
"workspaces": ["packages/*", "apps/*"],
"dependencies": {
"shared-pkg": "workspace:*"
}
}
包管理:
bun pm trust <pkg> # Allow lifecycle scripts
bun pm untrusted # View blocked scripts
bun why <pkg> # Explain why package installed
bun outdated # Show outdated packages
bun audit # Security vulnerability check
bun patch <pkg> # Prepare package for patching
bun link # Link local packages
**锁文件:**Bun 使用 bun.lock(基于文本的 JSONC 格式),易于阅读且可通过 git diff 查看差异。它会自动从 package-lock.json、yarn.lock 或 pnpm-lock.yaml 迁移。
3. 测试运行器(bun:test)
测试语法:
import { describe, test, expect, beforeAll, afterEach, mock, spyOn } from "bun:test";
describe("feature", () => {
beforeAll(() => { /* setup */ });
afterEach(() => { mock.restore(); });
test("basic assertion", () => {
expect(2 + 2).toBe(4);
});
test("async operation", async () => {
const result = await fetchData();
expect(result).toMatchObject({ status: "ok" });
});
test.each([[1, 2, 3], [2, 3, 5]])("adds %i + %i = %i", (a, b, expected) => {
expect(a + b).toBe(expected);
});
});
测试修饰符:
test.skip()- 跳过测试test.only()- 仅运行此测试(需使用--only标志)test.todo()- 将测试标记为待办test.if(condition)/test.skipIf(condition)- 条件执行test.failing()- 预期会失败test.concurrent- 并发运行test.retry(n)- 重试失败的测试
常用匹配器:
.toBe()、.toEqual()、.toStrictEqual()- 相等性.toContain()、.toHaveLength()、.toMatch()- 字符串/数组.toHaveProperty()、.toMatchObject()- 对象.toThrow()、.rejects.toThrow()- 错误.toMatchSnapshot()、.toMatchInlineSnapshot()- 快照.toHaveBeenCalled()、.toHaveBeenCalledWith()- 模拟
模拟:
import { mock, spyOn } from "bun:test";
const mockFn = mock(() => 42);
mockFn.mockImplementation(() => 100);
mockFn.mockReturnValue(200);
const spy = spyOn(object, "method");
spy.mockResolvedValue({ data: "test" });
// Module mocking
mock.module("./api", () => ({
fetchUser: mock(() => ({ id: 1, name: "Test" }))
}));
CLI 命令:
bun test # Run all tests
bun test --watch # Watch mode
bun test --coverage # Enable coverage
bun test -t "pattern" # Filter by test name
bun test --timeout=5000 # Set timeout
bun test --bail # Stop on first failure
bun test --update-snapshots # Update snapshots
4. 打包器配置
JavaScript API:
const result = await Bun.build({
entrypoints: ["./src/index.tsx"],
outdir: "./dist",
target: "browser", // "browser" | "bun" | "node"
format: "esm", // "esm" | "cjs" | "iife"
minify: true,
sourcemap: "external",
splitting: true, // Code splitting
external: ["react", "react-dom"],
define: {
"process.env.NODE_ENV": '"production"'
},
loader: {
".png": "dataurl",
".svg": "text"
},
plugins: [myPlugin],
naming: {
entry: "[dir]/[name].[ext]",
chunk: "[name]-[hash].[ext]"
}
});
if (!result.success) {
console.error(result.logs);
}
CLI:
bun build ./src/index.tsx --outdir ./dist --minify --sourcemap=external
bun build ./src/index.ts --compile --outfile myapp # Single executable
插件系统:
const myPlugin: BunPlugin = {
name: "yaml-loader",
setup(build) {
build.onLoad({ filter: /\.yaml$/ }, async (args) => {
const text = await Bun.file(args.path).text();
return {
contents: `export default ${JSON.stringify(YAML.parse(text))}`,
loader: "js"
};
});
}
};
5. TypeScript 集成
Bun 无需转译配置即可原生执行 TypeScript:
bun run index.ts # Just works
bun run index.tsx # JSX supported
推荐的 tsconfig.json:
{
"compilerOptions": {
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"types": ["bun-types"]
}
}
类型检查(单独步骤):
bunx tsc --noEmit
6. 配置(bunfig.toml)
# Runtime
preload = ["./setup.ts"]
smol = true # Reduced memory mode
# JSX
[jsx]
runtime = "automatic"
importSource = "react"
# Package installation
[install]
optional = false
lockfile.save = true
[install.scopes]
"@myorg" = { url = "https://npm.myorg.com", token = "$NPM_TOKEN" }
# Test runner
[test]
preload = ["./test-setup.ts"]
coverage = true
coverageThreshold = { lines = 0.8, functions = 0.8 }
7. CLI 标志参考
执行:
--watch- 文件更改时自动重启--hot- 热模块替换--smol- 降低内存占用模式--inspect/--inspect-brk- 调试器
模块解析:
--preload/-r- 预加载模块--install=auto|fallback|force- 自动安装行为
转译:
--define/-d- 编译时常量--drop=console- 移除函数调用--loader- 自定义文件加载器
环境:
--env-file- 加载指定的 .env 文件--cwd- 设置工作目录--bun/-b- 强制使用 Bun 运行时
Node.js 迁移指南
快速迁移步骤
- 安装 Bun:
curl -fsSL https://bun.sh/install | bash - 替换包管理器:
# Delete node_modules and lockfile
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml
bun install
- 更新 package.json 中的脚本:
{
"scripts": {
"dev": "bun run --watch src/index.ts",
"test": "bun test",
"build": "bun build src/index.ts --outdir dist"
}
}
- 更新 TypeScript 类型:
bun add -d @types/bun
# Or in tsconfig.json: "types": ["bun-types"]
API 兼容性
完全兼容:
node:assert、node:buffer、node:events、node:path、node:urlnode:fs(92%)、node:http、node:https、node:stream、node:zlibnode:crypto、node:net、node:dns、node:os
部分兼容:
node:child_process- 缺少proc.gid、proc.uid;IPC 仅支持 JSONnode:cluster- 仅 Linux 支持用于负载均衡的 SO_REUSEPORTnode:http2- 95% 兼容;缺少pushStreamnode:worker_threads- 缺少stdin、stdout、stderr选项node:async_hooks- AsyncLocalStorage 可用;缺少 v8 promise hooks
尚未实现:
node:inspector、node:repl、node:trace_events
常见迁移注意事项
- 原生模块: 使用 node-gyp 的软件包(bcrypt、sharp)可能无法运行
- 解决方案:使用纯 JS 替代方案(例如用
bcryptjs替代bcrypt)
- 解决方案:使用纯 JS 替代方案(例如用
- 生命周期脚本: Bun 默认阻止 postinstall(安全措施)
- 解决方案:使用
bun pm trust <package>,或将其添加到trustedDependencies
- 解决方案:使用
- 模块系统: 依赖 Node.js 内部实现的某些软件包可能无法运行
- Bun 中不存在
Module._nodeModulePaths
- Bun 中不存在
- 文件系统差异: 大量并发读取文件可能导致内存问题
- 解决方案:使用
graceful-fs封装器
- 解决方案:使用
- TypeScript 入口点: 为 Bun 更新
"main"字段:
{
"main": "src/index.ts" // Not "build/index.js"
}
渐进式迁移策略
阶段 1: 仅使用包管理器(bun install)
阶段 2: 使用开发工具(bun run、bun test)
阶段 3: 选择性迁移运行时(影子部署)
阶段 4: 完整迁移到生产环境
最佳实践
性能优化
// Use Bun's native APIs for I/O
const file = Bun.file("large.txt"); // Zero-copy
const content = await file.text();
await Bun.write("output.txt", processedData);
// Use Promise.all for concurrent operations
const [users, posts] = await Promise.all([
db.query("SELECT * FROM users"),
db.query("SELECT * FROM posts")
]);
// Use Bun.serve() static routes
Bun.serve({
static: {
"/": homepage,
"/about": aboutPage
},
fetch(req) { /* dynamic routes */ }
});
// Use bun:sqlite for local data
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
错误处理
// HTTP server error handling
Bun.serve({
fetch(req) {
try {
return handleRequest(req);
} catch (error) {
console.error(error);
return new Response("Internal Error", { status: 500 });
}
},
error(error) {
return new Response(`Error: ${error.message}`, { status: 500 });
}
});
// Process-level error handling
process.on("uncaughtException", (error) => {
console.error("Uncaught:", error);
process.exit(1);
});
安全最佳实践
- 生命周期脚本: 尽量精简
trustedDependencies - 环境变量: 使用
.env.local存放机密信息(不要提交) - 输入验证: 清理所有用户输入
- 依赖项: 定期运行
bun audit - 生产环境: 使用
--production标志跳过 devDependencies
项目结构
my-bun-project/
├── src/
│ ├── index.ts # Entry point
│ ├── server.ts # HTTP server
│ └── lib/ # Utilities
├── test/
│ └── *.test.ts # Test files
├── bunfig.toml # Bun configuration
├── tsconfig.json # TypeScript config
├── package.json
└── .env.local # Local secrets (gitignored)
调试
Web 调试器:
bun --inspect server.ts # Start debugger
bun --inspect-brk server.ts # Break at first line
bun --inspect-wait server.ts # Wait for connection
打开 https://debug.bun.sh,或使用 VSCode Bun 扩展。
详细的 Fetch 日志:
BUN_CONFIG_VERBOSE_FETCH=curl bun run server.ts
示例
使用 WebSocket 的 HTTP 服务
Bun.serve({
port: 3000,
fetch(req, server) {
if (server.upgrade(req)) return;
return new Response("Hello Bun!");
},
websocket: {
open(ws) { console.log("Connected"); },
message(ws, message) { ws.send(`Echo: ${message}`); },
close(ws) { console.log("Disconnected"); }
}
});
文件服务
Bun.serve({
async fetch(req) {
const path = new URL(req.url).pathname;
const file = Bun.file(`./public${path}`);
if (await file.exists()) {
return new Response(file);
}
return new Response("Not Found", { status: 404 });
}
});
使用 SQLite 的数据库
import { Database } from "bun:sqlite";
const db = new Database("app.db");
db.run(`CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
)`);
const insert = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
const getAll = db.prepare("SELECT * FROM users");
insert.run("Alice", "[email protected]");
const users = getAll.all();
此技能的激活条件
在以下情况下,此技能会自动激活:
- 在 Bun 项目中处理
.ts、.tsx、.js、.jsx文件 - 创建或修改
bunfig.toml或bun.lock - 使用
bun:test、bun:sqlite、bun:ffi导入 - 讨论 Bun API(Bun.serve、Bun.file、Bun.build)
- 从 Node.js 迁移到 Bun
- 编写或调试 Bun 测试
- 配置 Bun 打包器