Bun v1.3 深度解析:内置数据库、零配置前端与 SIMD 暴力优化——JavaScript 工具链的终极一体化
一行
bun ./index.html跑起前端,一行new SQL("postgres://...")连上数据库,一行bun build --compile打出可执行文件——这不是梦想,这是 Bun v1.3 的日常。
一、引子:JavaScript 工具链的「万国牌」困境
2026 年,一个典型的 JavaScript 全栈项目需要多少个工具?
运行时: Node.js
包管理器: npm / yarn / pnpm
TypeScript: tsc + ts-node + tsconfig.json
打包器: Webpack / Vite / Rollup
测试框架: Jest / Vitest
开发服务器: webpack-dev-server / vite dev
热更新: react-refresh / webpack-hot-middleware
数据库驱动: pg + mysql2 + ioredis + better-sqlite3
环境变量: dotenv
代码格式化: Prettier
代码检查: ESLint
进程管理: pm2 / nodemon
12+ 个工具,12+ 个配置文件,12+ 个版本要维护。每增加一个工具,就多一分「依赖地狱」的风险。
Bun v1.3 的回答是:全部内置,一个二进制文件搞定一切。
这不是简单的「集成」,而是从底层重新设计——用 Zig 语言直接调用 JavaScriptCore 的 C API,把数据库驱动、前端开发服务器、打包器、测试框架、Redis 客户端全部编译进同一个可执行文件。
v1.3 是 Bun 迄今为止最大的版本更新,带来了内置数据库客户端、零配置前端开发模式、原生 HMR、交叉编译为独立可执行文件等重磅特性。
二、Bun v1.3 核心新特性一览
| 特性 | 之前 | v1.3 |
|---|---|---|
| 数据库连接 | 安装 pg/mysql2/ioredis/better-sqlite3 | import { SQL } from "bun" 直接用 |
| 前端开发 | 配置 Vite/Webpack + 插件 | bun ./index.html 零配置启动 |
| 热模块替换 | 安装 react-refresh 等中间件 | 内置 HMR + React Fast Refresh |
| 可执行文件 | 需要 pkg 或 nexe | bun build --compile 原生支持 |
| Redis | 安装 ioredis | Bun.connect() 内置客户端 |
| YAML 处理 | 安装 js-yaml | Bun.YAML 内置 |
| CSRF 保护 | 安装 csurf | Bun.CSRF 内置 |
| 密钥管理 | 安装 keytar | Bun.secrets 系统原生凭据存储 |
| 定时任务 | 安装 node-cron | Bun.cron 内置 |
| Markdown | 安装 marked/remark | Bun.markdown 内置 |
| 安全审计 | 安装 npm audit | bun audit 内置 |
三、内置数据库客户端:SQL 的终极统一
3.1 统一 SQL API(Bun.SQL)
这是 v1.3 最具颠覆性的特性。一个 SQL 类,三种数据库,语法完全一致:
import { SQL } from "bun";
// PostgreSQL
const pg = new SQL("postgres://user:pass@localhost:5432/mydb");
// MySQL / MariaDB
const mysql = new SQL("mysql://user:pass@localhost:3306/mydb");
// SQLite
const sqlite = new SQL("sqlite://./data.db");
// 统一的查询语法——切换数据库只需改连接字符串
const users = await pg`SELECT * FROM users WHERE active = ${true}`;
注意那个模板字符串语法——await db\SQL...`不是普通的字符串拼接,而是 **参数化查询**。变量${true}` 会被安全地参数化,而不是直接拼进 SQL 字符串,从根本上防止 SQL 注入。
3.2 参数化查询的实现原理
// 这行代码:
await db`SELECT * FROM users WHERE id = ${userId} AND active = ${true}`;
// 实际发送给数据库的是:
// SELECT * FROM users WHERE id = $1 AND active = $2
// 参数: [userId, true]
Bun 的模板标签函数在编译期将模板字符串拆分为静态 SQL 片段和参数占位符,运行时只传递参数值,不进行字符串拼接。这比手动写 db.query(sql, [params]) 更安全,也更符合直觉。
3.3 PostgreSQL 高级特性
const pg = new SQL("postgres://localhost:5432/mydb");
// 简单查询协议(支持多语句)
const results = await pg.simple(`
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');
`);
// Unix Domain Sockets 连接(本地开发更快)
const localPg = new SQL("postgres:///var/run/postgresql/.s.PGSQL.5432/mydb");
// 动态列操作
const columns = ["name", "email"];
const data = await db`SELECT ${SQL.columns(columns)} FROM users`;
3.4 内置 Redis 客户端
v1.3 新增了高性能 Redis/Valkey 客户端,支持 66+ 种命令:
const redis = await Bun.connect({
hostname: "localhost",
port: 6379,
password: "your-password", // 可选
});
// 基本操作
await redis.set("user:1001", JSON.stringify({ name: "Alice" }));
const user = await redis.get("user:1001");
// 带过期时间
await redis.setex("session:abc123", 3600, "user_data");
// 自增/自减
await redis.incr("page:views");
// Hash 操作
await redis.hset("user:1001", "name", "Alice");
await redis.hset("user:1001", "email", "alice@example.com");
const name = await redis.hget("user:1001", "name");
// Pub/Sub
await redis.subscribe("notifications", (message) => {
console.log("收到通知:", message);
});
// 发布消息
await redis.publish("notifications", "新订单到达!");
3.5 为什么内置数据库驱动这么重要?
传统 Node.js 项目的数据库连接有多麻烦?
# 安装 PostgreSQL 驱动
npm install pg
# 还要装类型定义
npm install -D @types/pg
# 环境变量
npm install dotenv
# 连接池
npm install pg-pool
# 如果还用 MySQL
npm install mysql2
npm install -D @types/mysql2
# 如果还用 Redis
npm install ioredis
5 个包,5 个版本,5 份文档。Bun v1.3 把这些都编译进了二进制文件——零安装、零配置、零类型定义(因为 TypeScript 类型是内置的)。
更重要的是性能。Bun 的 PostgreSQL 客户端比 Node.js 的 pg 快 2 倍,因为:
- 零拷贝解析:Zig 直接解析 PostgreSQL wire protocol,不经过 JavaScript 中间层
- 连接池内置:默认启用连接池,不需要额外配置
pg-pool - 批量查询优化:自动将多个查询合并为一次网络往返
四、零配置前端开发:Vite 的终结者?
4.1 从 HTML 开始
Bun v1.3 引入了直接运行 HTML 文件的能力:
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./App.tsx"></script>
</body>
</html>
// App.tsx
import { useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(c => c + 1)}>+1</button>
</div>
);
}
# 开发模式(自动启动 HMR)
bun ./index.html
# 生产构建
bun build --production
没有 vite.config.ts,没有 @vitejs/plugin-react,没有 tsconfig.json 的 JSX 配置。Bun 自动识别 JSX/TSX 文件,自动安装 React 依赖,自动启动开发服务器。
4.2 自动依赖安装
当你运行 bun ./index.html 时,如果 React 没有安装,Bun 会自动帮你安装:
$ bun ./index.html
Installing react@19 react-dom@19...
✓ Installed in 0.8s
bun dev v1.3.0
> localhost:3000
这个「自动安装」不是简单的 bun install react,而是基于静态分析——Bun 解析你的源代码中的 import 语句,自动识别缺失的依赖并安装。
4.3 热模块替换(HMR)
Bun 内置了完整的 HMR 支持:
- 文件监听:macOS 使用 kqueue,Linux 使用 inotify(平台原生 API,零开销)
- React Fast Refresh:保留组件状态的热更新
- CSS 热更新:样式变更无需刷新页面
- 错误覆盖层:语法错误和运行时错误直接显示在浏览器中
// 保存后自动热更新,组件状态不丢失
export default function App() {
const [count, setCount] = useState(0); // 修改其他代码时,count 不会重置
return <h1>{count}</h1>; // ← 修改这里,页面即时更新
}
4.4 与 Vite 的对比
| 维度 | Bun | Vite |
|---|---|---|
| 配置文件 | 无(零配置) | vite.config.ts |
| React 支持 | 内置 | 需要安装 @vitejs/plugin-react |
| TypeScript 支持 | 内置 | 内置(但 JSX 需配置) |
| 数据库访问 | 内置 SQL API | 需要 API 服务器 |
| 打包 | 内置 bun build | 需要安装 Rollup |
| 安装依赖 | 自动 | 手动 npm install |
| 启动速度 | ~50ms | ~300ms |
| HMR 速度 | ~10ms | ~50ms |
当然,Vite 的插件生态系统更成熟,自定义能力更强。但对于 80% 的标准 React 项目来说,Bun 的零配置体验已经足够。
五、编译为独立可执行文件
5.1 基本用法
# 编译为当前平台的可执行文件
bun build --compile ./src/index.ts --outfile myapp
# 运行
./myapp
输出是一个独立的可执行文件,不需要 Node.js、不需要 node_modules、不需要 Bun 本身。用户只需下载一个文件就能运行你的应用。
5.2 交叉编译
# 为 Linux x64 编译(在 macOS 上)
bun build --compile --target=bun-linux-x64 ./src/index.ts --outfile myapp-linux
# 为 Windows x64 编译
bun build --compile --target=bun-windows-x64 ./src/index.ts --outfile myapp.exe
# 为 macOS ARM64 编译
bun build --compile --target=bun-darwin-arm64 ./src/index.ts --outfile myapp-mac
支持的目标平台:
bun-linux-x64bun-linux-arm64bun-darwin-x64(macOS Intel)bun-darwin-arm64(macOS Apple Silicon)bun-windows-x64
5.3 代码签名
v1.3 新增了代码签名支持:
# macOS .app 签名
codesign --sign "Developer ID Application: Your Name" myapp-mac
# Windows .exe 签名(需要 Signtool)
signtool sign /f certificate.pfx /p password myapp.exe
这解决了分发可执行文件时的安全问题——用户不会看到「未知开发者」的警告。
5.4 全栈应用打包实战
// server.ts — 全栈应用入口
import { SQL } from "bun";
const db = new SQL("sqlite://./data.db");
// 初始化数据库
await db`CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`;
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
// API 路由
if (url.pathname === "/api/notes" && req.method === "GET") {
const notes = await db`SELECT * FROM notes ORDER BY created_at DESC`;
return Response.json(notes);
}
if (url.pathname === "/api/notes" && req.method === "POST") {
const { content } = await req.json();
const result = await db`INSERT INTO notes (content) VALUES (${content}) RETURNING *`;
return Response.json(result[0], { status: 201 });
}
// 静态文件(编译时嵌入)
const file = Bun.file(`./public${url.pathname === "/" ? "/index.html" : url.pathname}`);
if (await file.exists()) {
return new Response(file);
}
return new Response("Not Found", { status: 404 });
},
});
console.log(`Server running at http://localhost:${server.port}`);
# 打包为可执行文件
bun build --compile ./server.ts --outfile notes-app
# 分发!用户只需下载一个文件
./notes-app
六、SIMD 优化:Bun 2026 的性能暗线
除了 v1.3 的新功能,Bun 在 2026 年初还进行了全面的 SIMD 指令集优化。这不是零星的性能补丁,而是贯穿整个技术栈的战略选择。
6.1 什么是 SIMD?
SIMD(Single Instruction, Multiple Data)是一种 CPU 指令集扩展,允许一条指令同时处理多个数据。比如普通的加法一次只能加两个数,而 SIMD 的 __m256i 寄存器一次可以加 8 个 32 位整数。
Bun 使用 Zig 的 @vector 语法直接编写 SIMD 代码:
// Zig 中的 SIMD 向量操作
const Vec8u32 = @Vector(8, u32);
pub fn sumSlice(slice: []const u32) u32 {
var acc: Vec8u32 = @splat(0);
var i: usize = 0;
const len = slice.len - (slice.len % 8);
while (i < len) : (i += 8) {
const chunk: Vec8u32 = slice[i..][0..8].*;
acc = acc + chunk;
}
var total: u32 = 0;
for (@as([8]u32, acc)) |val| {
total += val;
}
// 处理剩余元素
while (i < slice.len) : (i += 1) {
total += slice[i];
}
return total;
}
6.2 Bun 中的 SIMD 优化成果
| 优化点 | 加速倍数 | 原理 |
|---|---|---|
| Buffer.indexOf | 2x | SSE4.2 PCMPESTRI 指令并行字节搜索 |
| RegExp 前缀匹配 | 3.9x | SIMD 快速跳过不可能的匹配位置 |
| CRC32 计算 | 20x | 硬件 CRC32C 指令替代软件实现 |
| Markdown 渲染 | 持续优化 | SIMD 加速 HTML 转义和文本扫描 |
| Base64 编解码 | 4x | 向量化查表 + SIMD 合并 |
| JSON 解析(长字符串) | 2-4x | SIMD 跳过空白字符和字符串扫描 |
6.3 Buffer.indexOf 的 SIMD 实现剖析
传统实现:
// 传统逐字节搜索
function indexOf(buffer, needle) {
for (let i = 0; i < buffer.length - needle.length; i++) {
let found = true;
for (let j = 0; j < needle.length; j++) {
if (buffer[i + j] !== needle[j]) {
found = false;
break;
}
}
if (found) return i;
}
return -1;
}
SIMD 优化(Zig 伪代码):
pub fn indexOfSimd(haystack: []const u8, needle: u8) ?usize {
const vec_len = 32; // AVX2: 256-bit = 32 bytes
const Vec32u8 = @Vector(32, u8);
const Vec32bool = @Vector(32, bool);
const needle_vec: Vec32u8 = @splat(needle);
var i: usize = 0;
const aligned_len = haystack.len - (haystack.len % vec_len);
while (i < aligned_len) : (i += vec_len) {
const chunk: Vec32u8 = haystack[i..][0..vec_len].*;
const eq: Vec32bool = chunk == needle_vec;
// 一次比较 32 个字节!
if (@reduce(.Or, eq)) {
// 找到了,定位具体位置
const mask = @bitCast(u32, eq);
return i + @ctz(mask);
}
}
// 处理尾部
for (haystack[i..]) |byte, idx| {
if (byte == needle) return i + idx;
}
return null;
}
关键区别:传统实现每次循环比较 1 个字节,SIMD 实现每次循环比较 32 个字节。在搜索大 Buffer 时,这直接带来 ~2 倍的性能提升。
七、包管理器增强:企业级功能落地
7.1 安全审计:bun audit
# 检查依赖中的已知漏洞
$ bun audit
2 vulnerabilities found:
CRITICAL prototype-pollution in lodash@4.17.20
Used by: my-app > utils > lodash
Fix: bun update lodash
MODERATE reDoS in glob@7.2.0
Used by: my-app > build-tool > glob
Fix: bun update glob
7.2 依赖追溯:bun why
# 为什么安装了这个包?
$ bun why lodash
lodash@4.17.21
my-app
└── utils@2.1.0
└── lodash@4.17.21 (dependency)
7.3 依赖目录(Catalogs):Monorepo 的救星
# bunfig.toml
[catalog]
react = "19.0.0"
typescript = "5.8.0"
[catalog.dev]
"@types/react" = "19.0.0"
在 monorepo 中,所有 workspace 共用同一个版本的 React,不需要在每个 package.json 里手动同步版本号。
7.4 最小发布年龄:防止供应链攻击
# bunfig.toml
[install]
min-age = 86400000 # 24小时,单位毫秒
设置后,Bun 不会安装发布时间不到 24 小时的包。这可以有效防止恶意包被快速发布后立刻被安装——大多数恶意包在发布后几小时内就会被社区发现并下架。
八、测试框架:与 Jest 的最终对决
8.1 基本用法
// math.test.ts
import { expect, describe, it, test } from "bun:test";
describe("数学工具函数", () => {
it("应该正确计算两数之和", () => {
expect(add(1, 2)).toBe(3);
});
// 并发测试
test.concurrent("应该处理并发请求", async () => {
const result = await fetchParallel(urls);
expect(result.length).toBe(urls.length);
});
// 预期失败的测试
test.failing("这个功能还没实现", () => {
expect(unimplemented()).toBe(true);
});
// 类型测试
test("类型检查", () => {
expectTypeOf(add).returns.toBeNumber();
expectTypeOf(add).parameters.toEqualTypeOf<[number, number]>();
});
});
8.2 与 Jest 的性能对比
项目:50,000 个测试用例
Bun: 12 秒
Jest: 14 分 22 秒
加速比:~72x
Bun 测试框架快的原因:
- 单进程:Jest 每个 test file 启动一个 worker 进程,Bun 在同一进程中运行所有测试
- 无转译开销:直接运行 TypeScript,不需要 babel-jest 转译
- 内置断言:不需要导入断言库,减少模块加载时间
8.3 VS Code 集成
v1.3 新增了 VS Code 测试资源管理器集成,可以直接在编辑器中运行和调试测试,不需要额外的扩展。
九、完整 HTTP 服务器示例:25 行代码的全栈应用
// app.ts
import { SQL, serve } from "bun";
const db = new SQL("sqlite://./notes.db");
await db`CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`;
serve({
port: 3000,
routes: {
"/": new Response(Bun.file("./public/index.html")),
"/api/notes": {
GET: async () => {
const notes = await db`SELECT * FROM notes ORDER BY created_at DESC LIMIT 50`;
return Response.json(notes);
},
POST: async (req) => {
const { content } = await req.json();
const [note] = await db`INSERT INTO notes (content) VALUES (${content}) RETURNING *`;
return Response.json(note, { status: 201 });
},
},
},
});
console.log("🚀 http://localhost:3000");
# 开发
bun --watch app.ts
# 生产
bun build --compile app.ts --outfile notes-app
./notes-app
25 行代码,包含:数据库初始化、REST API、静态文件服务、路由。
十、Bun vs Node.js vs Deno:2026 年终极对比
10.1 性能基准
| 场景 | Bun | Node.js 22 | Deno 2.0 |
|---|---|---|---|
| HTTP 吞吐量 | 128K req/s | 52K req/s | ~100K req/s |
| 包安装(1000+ 依赖) | 数秒 | 1-3 分钟 | ~30 秒 |
| 测试运行(50k 测试) | 12 秒 | 14+ 分钟(Jest) | ~2 分钟 |
| 打包 10 个 three.js | 269ms | ~59 秒(Webpack) | ~10 秒 |
| 冷启动 | ~4ms | ~16ms | ~8ms |
| React HMR | ~10ms | ~50ms(Vite) | ~30ms |
10.2 功能覆盖
| 功能 | Bun | Node.js | Deno |
|---|---|---|---|
| TypeScript 原生运行 | ✅ | ❌(需 tsc) | ✅ |
| JSX/TSX 原生支持 | ✅ | ❌(需 Babel) | ✅ |
| 内置数据库驱动 | ✅ | ❌ | ❌ |
| 内置 Redis | ✅ | ❌ | ❌ |
| 内置测试框架 | ✅ | ❌(需 Jest) | ✅ |
| 内置打包器 | ✅ | ❌(需 Webpack) | ✅ |
| 内置格式化 | ❌ | ❌(需 Prettier) | ✅ |
| 内置 Lint | ❌ | ❌(需 ESLint) | ✅ |
| 安全沙箱 | ❌ | ❌ | ✅ |
| LTS 支持 | ❌ | ✅ | ✅(2.0+) |
| npm 兼容性 | ~90% | 100% | 大多数 |
10.3 选型建议
| 场景 | 推荐 | 理由 |
|---|---|---|
| 新全栈项目 | Bun | 一体化工具链,开发效率最高 |
| 高并发 API / Serverless | Bun | 启动快,吞吐高,冷启动开销最小 |
| 企业级大型系统 | Node.js | LTS + 成熟生态 + 稳定性 |
| 安全优先的 CLI/工具 | Deno | 沙箱权限模型 |
| 老项目维护 | Node.js | 兼容性最好 |
| 需要长期支持 | Node.js/Deno | Bun 无 LTS |
十一、局限性:Bun 还不能做什么
11.1 稳定性风险
Bun 的快速迭代是一把双刃剑。虽然新特性不断,但偶有内存泄漏和段错误。对于要求 99.99% 可用性的生产环境,Bun 的可靠性还需要更长时间的验证。
11.2 Node.js 兼容性并非 100%
未实现的模块:node:repl、node:trace_events 等
部分实现的模块:node:cluster、node:worker_threads 的高级功能
深度依赖 Node.js 特定 API 的项目可能面临兼容性问题。在迁移前,建议用 bun compat 命令检查兼容性。
11.3 Windows 原生支持不完善
目前推荐通过 WSL 使用 Bun。原生 Windows 支持存在一些已知问题,特别是涉及文件系统监听和权限管理的场景。
11.4 无 LTS 机制
Bun 采用快速迭代策略,没有提供长期支持版本。企业级项目需要稳定的运行时版本和长期的安全补丁支持。
11.5 TypeScript 不做类型检查
Bun 只负责 TypeScript 的转译,不执行类型检查。你仍需在 CI 中运行 tsc --noEmit 进行类型校验。
十二、实战:从零搭建 Bun 全栈应用
12.1 项目初始化
# 创建项目
mkdir my-bun-app && cd my-bun-app
bun init
# 项目结构
my-bun-app/
├── src/
│ ├── index.ts # 服务器入口
│ ├── db.ts # 数据库配置
│ └── routes/
│ ├── users.ts # 用户 API
│ └── notes.ts # 笔记 API
├── public/
│ ├── index.html
│ └── App.tsx
├── tests/
│ └── api.test.ts
├── bunfig.toml
└── package.json
12.2 数据库层
// src/db.ts
import { SQL } from "bun";
export const db = new SQL(
process.env.DATABASE_URL || "sqlite://./dev.db"
);
// 自动迁移
export async function migrate() {
await db`
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
)
`;
await db`
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id),
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`;
}
12.3 服务器
// src/index.ts
import { SQL } from "bun";
import { db, migrate } from "./db";
await migrate();
const server = Bun.serve({
port: process.env.PORT || 3000,
async fetch(req) {
const url = new URL(req.url);
// CORS
if (req.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
"Access-Control-Allow-Headers": "Content-Type",
},
});
}
// API 路由
if (url.pathname === "/api/users" && req.method === "GET") {
const users = await db`SELECT id, name, email FROM users`;
return Response.json(users);
}
if (url.pathname === "/api/users" && req.method === "POST") {
const { name, email } = await req.json();
try {
const [user] = await db`
INSERT INTO users (name, email) VALUES (${name}, ${email})
RETURNING id, name, email
`;
return Response.json(user, { status: 201 });
} catch (e) {
return Response.json({ error: "Email already exists" }, { status: 409 });
}
}
// 前端
if (url.pathname === "/" || url.pathname === "/index.html") {
return new Response(Bun.file("./public/index.html"));
}
return new Response("Not Found", { status: 404 });
},
});
console.log(`🚀 Server at http://localhost:${server.port}`);
12.4 测试
// tests/api.test.ts
import { expect, describe, it, beforeAll } from "bun:test";
const BASE = "http://localhost:3000";
describe("用户 API", () => {
it("GET /api/users 返回用户列表", async () => {
const res = await fetch(`${BASE}/api/users`);
expect(res.status).toBe(200);
const users = await res.json();
expect(Array.isArray(users)).toBe(true);
});
it("POST /api/users 创建用户", async () => {
const res = await fetch(`${BASE}/api/users`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Test User",
email: `test-${Date.now()}@example.com`,
}),
});
expect(res.status).toBe(201);
const user = await res.json();
expect(user.name).toBe("Test User");
});
it("POST /api/users 重复邮箱返回 409", async () => {
const body = { name: "Dup", email: "dup@example.com" };
await fetch(`${BASE}/api/users`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const res = await fetch(`${BASE}/api/users`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
expect(res.status).toBe(409);
});
});
# 运行测试
bun test
十三、总结:Bun v1.3 的意义
Bun v1.3 不是一个简单的版本更新,而是 JavaScript 工具链的一次范式转移:
- 从「组合」到「一体」:不需要组合 12+ 个工具,一个二进制文件搞定一切
- 从「配置」到「零配置」:
bun ./index.html直接跑,不需要写配置文件 - 从「安装」到「内置」:数据库驱动、Redis、YAML、CSRF 全部内置
- 从「解释」到「编译」:SIMD 优化让 JavaScript 运行时逼近 C 性能
当然,Bun 还不完美——稳定性、Windows 支持、LTS 机制都是需要持续改进的方向。但对于新项目、追求效率的团队、以及想要简化工具链的开发者来说,Bun v1.3 已经是一个值得认真考虑的选择。
一句话总结:Bun v1.3 做的不是替代 Node.js,而是重新定义「JavaScript 开发应该是什么样子」。
项目资源
- 官方文档:https://bun.sh/docs
- GitHub:https://github.com/oven-sh/bun(88,000+ Stars)
- v1.3 发布公告:https://bun.sh/blog/bun-v1.3
- 中文文档站:https://bun.net.cn/
本文基于 Bun v1.3 官方文档、CSDN 技术分析文章和 Bun 官方基准测试数据撰写。实际性能因硬件、操作系统和项目复杂度而异,建议在自身环境中进行实测。