npm install等到你泡完咖啡?Bun 1.3来了,8秒装完整个项目

你有没有算过,一天在等npm install上花了多少时间
前端开发有一种独特的痛苦:你的代码已经写好了,你的思路正在线上,但你得等。等npm install跑完,等webpack编译完,等TypeScript编译器慢悠悠地检查完类型,再等Babel转译一遍。Bun 1.3说它能把这些等待时间砍掉90%,我试了一下,还真没吹牛。
这种感觉就像你在高速公路上开到120码,突然前面出现了一个收费站。你不是不能到达目的地,你只是得停下来,等着那个杆子抬起来。
我之前在一个Remix项目上做过计时:npm install跑了3分20秒。三分二十秒,够我去茶水间倒杯水、刷两条朋友圈、再回来发现进度条才走到80%。
2025年10月,Bun发布了1.3版本。同一个Remix项目,bun install跑了8秒。
不是我打错了。8秒。从3分20秒到8秒,快了25倍。
先说清楚Bun是什么,不然后面的都白聊
很多人第一次听说Bun的反应是:“又一个JavaScript运行时?Node.js不够用吗?”
这个反应很正常。JavaScript生态三天两头冒出个新工具,大部分活不过半年。但Bun不一样,它不是来替代Node.js的某一个功能的,它是来替代你工具箱里一半东西的。
打个比方:Node.js像一把瑞士军刀的刀片,你还得自己配开瓶器(npm)、螺丝刀(webpack)、剪刀(Jest)、锯子(Babel)。Bun直接给你一把完整的瑞士军刀,开箱即用。
具体来说,Bun 1.3一个可执行文件里装了这些:
- 运行时 – 直接跑JavaScript和TypeScript
- 包管理器 – 替代npm、yarn、pnpm
- 打包工具 – 替代webpack、Vite、esbuild
- 测试框架 – 兼容Jest,但快10倍
- 转译器 – TypeScript不用配置直接跑
- 开发服务器 – 热更新开箱即用
你以前要装六七个工具才能搭起来的开发环境,现在一行命令搞定。
Bun性能实测:差距到底有多大
说性能不拿数据就是耍流氓。来看几组实际测试结果。
冷启动速度:
| 运行时 | 冷启动时间 |
|---|---|
| Bun 1.3 | 约8ms |
| Deno 2.5 | 约35ms |
| Node.js 24 | 约42ms |
Bun的冷启动比Node.js快了5倍多。对Serverless场景来说,这个差距直接影响账单。
HTTP请求处理能力(每秒请求数):
| 运行时 | req/s |
|---|---|
| Bun | 145,000 |
| Deno | 85,000 |
| Node.js | 65,000 |
同样的硬件,Bun每秒多处理8万个请求。放到生产环境里,这意味着你可以少开几台服务器,每个月少交一笔不小的云服务费。
包安装速度(大型Remix项目):
| 工具 | 安装时间 |
|---|---|
| Bun | 8秒 |
| npm | 3分20秒 |
这个差距在CI/CD流水线上尤其明显。你的流水线每天跑几十次,每次省3分钟,一个月下来省出来的时间够你多写好几个功能了。
Bun用JavaScriptCore和Zig,凭什么这么快
Bun快不是玄学,是技术选型上做了几个关键决定。
第一,换了引擎。 Node.js用的是Chrome的V8引擎,Bun用的是Apple维护的JavaScriptCore引擎(就是Safari里跑JavaScript的那个)。JavaScriptCore在启动速度和内存占用上有天然优势,代价是峰值计算性能稍逊于V8,但对大多数Web应用来说,启动快、内存省才是真金白银。
第二,底层用Zig写的。 Node.js底层是C++,Bun选了Zig。Zig是一门比C++更年轻的系统编程语言,给了开发者更精细的内存控制能力。C++像自动挡,Zig像手动挡 – 弯道里腾挪的空间大不少。
第三,一体化设计。 Node.js的各个工具(npm、webpack、Jest)是独立进程,互相通信有开销。Bun把所有功能塞进同一个进程,数据在内存里直接传递,不用序列化、不用跨进程通信。快递从仓库A转仓库B再到你手上,和从仓库直送到你家门口,你说哪个快?
Bun 1.3的几个杀手级功能
零配置前端开发
这个功能让我眼前一亮。你只需要:
bun index.html
就这一行。没有webpack配置文件,没有vite.config.ts。babel.config.js也不需要了。Bun自动帮你搞定:
- 热模块替换(HMR)
- React Fast Refresh
- TypeScript自动转译
- CSS导入处理
- 生产构建(
bun build --production)
回想一下你上次配webpack花了多长时间。那些在webpack.config.js里调了半天的loader和plugin,那些搜了一圈Stack Overflow才解决的配置冲突。现在不需要了。
内置SQL客户端:Bun.SQL
Bun 1.3内置了一个统一的数据库客户端,支持MySQL、MariaDB、PostgreSQL和SQLite,不需要装任何第三方依赖。
import { sql } from "bun";
// 查询用户列表
const users = await sql`
SELECT * FROM users
WHERE age > ${18}
ORDER BY created_at DESC
`;
// 用对象语法插入数据
const newUser = await sql`
INSERT INTO users ${sql({
name: "张三",
email: "zhangsan@example.com",
role: "developer"
})}
RETURNING *
`;
// 事务处理
await sql.transaction(async tx => {
await tx`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${fromId}`;
await tx`UPDATE accounts SET balance = balance + ${amount} WHERE id = ${toId}`;
});
注意看那个sql标签模板。参数自动做了SQL注入防护,不用你手动拼字符串。以前写个数据库查询,你得先装pg或者mysql2,再配连接池,再处理连接字符串 – 现在从"bun"里import一下就完事了。
内置Redis客户端
缓存是现代Web应用的基础设施。Bun 1.3直接内置了Redis客户端:
import { Redis } from "bun";
const redis = new Redis({
url: process.env.REDIS_URL || "redis://localhost:6379"
});
// 设置缓存
await redis.set("session:abc123", JSON.stringify(sessionData));
// 读取缓存
const session = JSON.parse(await redis.get("session:abc123"));
// 带过期时间的缓存
await redis.setex("otp:user123", 300, "987654"); // 5分钟后自动过期
又省了一个node-redis或者ioredis的依赖,少装一个包就少操一份心。
全栈路由API
这是Bun野心最大的功能。它想让你用一个文件写完前端加后端:
import { serve, sql } from "bun";
import App from "./frontend.html";
serve({
port: 3000,
routes: {
// 前端页面
"/*": App,
// API端点
"/api/users": {
GET: async () => {
const users = await sql`SELECT * FROM users LIMIT 50`;
return Response.json(users);
},
POST: async (req) => {
const data = await req.json();
const [user] = await sql`
INSERT INTO users ${sql(data)}
RETURNING *
`;
return Response.json(user, { status: 201 });
}
},
// 动态路由
"/api/users/:id": async (req) => {
const { id } = req.params;
const [user] = await sql`
SELECT * FROM users WHERE id = ${id}
`;
return user
? Response.json(user)
: new Response("Not Found", { status: 404 });
},
// 健康检查
"/health": Response.json({ status: "healthy" })
}
});
一个文件,前端、后端、数据库查询全有了。跑在同一个高度优化的进程里,快速原型开发的时候特别舒服。
实战:30秒搭一个任务管理API
光说不练假把式。来看看用Bun从零搭一个API到底有多快。
# 安装Bun(macOS/Linux)
curl -fsSL https://bun.sh/install | bash
# 创建项目
mkdir task-api && cd task-api
bun init -y
然后写一个app.ts:
import { serve, sql } from "bun";
// 建表(Bun内置SQLite支持)
await sql`
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`;
serve({
port: 3000,
routes: {
"/api/tasks": {
GET: async () => {
const tasks = await sql`SELECT * FROM tasks ORDER BY created_at DESC`;
return Response.json(tasks);
},
POST: async (req) => {
const { title } = await req.json();
if (!title) {
return Response.json({ error: "标题不能为空" }, { status: 400 });
}
const [task] = await sql`
INSERT INTO tasks ${sql({ title })}
RETURNING *
`;
return Response.json(task, { status: 201 });
}
},
"/api/tasks/:id/toggle": {
PATCH: async (req) => {
const { id } = req.params;
const [task] = await sql`
UPDATE tasks SET completed = NOT completed
WHERE id = ${id}
RETURNING *
`;
return task
? Response.json(task)
: new Response("任务不存在", { status: 404 });
}
}
}
});
console.log("任务API已启动: http://localhost:3000");
启动:
bun run app.ts
package.json里不需要一长串dependencies,ORM配置和数据库驱动安装也免了。代码写完,直接跑。
Bun内置测试框架:比Jest快10倍
Bun内置的测试框架兼容Jest语法,但跑起来快得多:
import { expect, test, describe } from "bun:test";
describe("任务API", () => {
test("创建任务", async () => {
const res = await fetch("http://localhost:3000/api/tasks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "学习Bun" })
});
expect(res.status).toBe(201);
const task = await res.json();
expect(task.title).toBe("学习Bun");
});
test("获取任务列表", async () => {
const res = await fetch("http://localhost:3000/api/tasks");
const tasks = await res.json();
expect(Array.isArray(tasks)).toBe(true);
});
});
运行测试:
bun test
Jest跑30秒的测试套件,Bun大约3秒跑完。这在TDD工作流中区别很大 – 你改一行代码,保存,3秒就知道测试过没过。而不是等半分钟,等到你已经忘了刚才改了什么。
从Node.js迁移过来难不难
说实话,比我预想的简单。大部分现代npm包在Bun上直接能跑。
第一步:用Bun装依赖
bun install # 自动读取package-lock.json,生成bun.lockb
第二步:改启动脚本
{
"scripts": {
"dev": "bun --watch src/index.ts",
"start": "bun src/index.ts",
"test": "bun test",
"build": "bun build src/index.ts --outdir dist --minify"
}
}
第三步:跑测试看看有没有兼容性问题
bun test
Express.js、Fastify、Hono这些主流框架都能直接跑。TypeScript原生支持,ES Modules和CommonJS都兼容。
真正可能踩坑的地方是那些依赖C++原生模块的包。如果你的项目里有sharp、bcrypt这类包,需要单独测试一下兼容性。Bun提供了bun pm trust命令来处理原生模块的信任问题。
Anthropic收购Bun意味着什么
2025年12月,Anthropic(就是做Claude那家公司)收购了Bun。这条消息在开发者圈子里炸了锅。
为什么一家AI公司要买一个JavaScript运行时?
因为Claude Code(Anthropic的AI编码工具)本身就是用Bun打包分发的。Claude Code在2025年5月公开发布后,半年时间做到了10亿美元的年化营收。Bun是Claude Code的基础设施,Anthropic需要确保它的长期稳定。
对普通开发者来说,这意味着两件事:
- Bun不会死。 有了大厂的资金支持,Bun的长期维护不用担心。
- Bun会跟AI开发工具深度整合。 未来可能会看到Bun在AI辅助开发方面有更多原生支持。
Bun依然是MIT协议开源,代码在GitHub上公开开发。Jarred Sumner(Bun的创始人)透露,Claude AI目前已经是Bun代码库最大的贡献者了。
什么时候该用Bun,什么时候不该
说了这么多好话,也得讲讲Bun的局限性。
适合用Bun的场景:
- 新项目启动,想尽快出活
- 对性能敏感的高并发API
- Serverless函数(冷启动快意味着省钱)
- CLI工具开发(Bun支持编译成单文件可执行程序)
- 全栈原型开发
暂时别急着换的场景:
- 老项目依赖了大量C++原生模块
- 生产环境对稳定性要求极高,团队还没时间做充分测试
- 你的部署平台还不支持Bun(不过Vercel已经支持了)
Node.js有15年的生态积累,社区规模和包数量还是碾压级的。Bun更像是那个打法凶猛的新人选手,老选手的底蕴还在。
Bun开发实用技巧
1. 不用装dotenv了
// 以前要这样
import dotenv from "dotenv";
dotenv.config();
// Bun自动加载.env文件,直接用
console.log(process.env.DATABASE_URL);
2. 文件操作有专门的API
// 写文件
await Bun.write("output.json", JSON.stringify(data));
// 读文件,自动解析JSON
const file = Bun.file("data.json");
const data = await file.json();
3. 编译成独立可执行文件
bun build ./cli.ts --compile --outfile mycli
./mycli --help
这对分发CLI工具太方便了。用户不需要装Node.js也不需要装Bun,直接一个可执行文件发过去就能用。
4. Watch模式开发
bun --watch index.ts # 文件改动自动重启
写在最后
JavaScript的工具链一直是前端开发被吐槽最多的地方。一个"hello world"项目的node_modules比项目本身大几百倍,这个梗已经讲了快十年了。
Bun 1.3在做的事情,是把散落在十几个工具里的功能收拢到一个地方。不是每个功能都做到最好,但在工程实践中,“够用且快"往往比"极致但复杂"更管用。
安装一下试试:
curl -fsSL https://bun.sh/install | bash
跑一下你现有的项目,看看那个安装速度和启动速度,你就知道我在说什么了。
常见问题
Bun能完全替代Node.js吗?
短期内不能。Node.js有15年的生态积累,npm上超过200万个包,大部分生产环境的运维经验都围绕Node.js建立。Bun的优势在新项目和性能敏感场景上最明显。两者会长期共存,就像你手机上同时装着微信和钉钉一样。
Bun 1.3的Bun.SQL支持哪些数据库?
MySQL、MariaDB、PostgreSQL和SQLite,不需要安装任何第三方驱动。SQL查询用标签模板语法,参数自动防注入。需要注意的是,这个内置SQL客户端适合中小规模应用,重度ORM场景可能还是需要Prisma或Drizzle这类工具。
我的Express项目能直接迁移到Bun吗?
大概率可以。Express.js是Bun官方明确支持的框架之一。最常见的问题出在依赖C++原生模块的npm包上(比如bcrypt、sharp)。建议先在开发环境跑一遍测试套件,确认没问题再往生产环境推。