你有没有算过,一天在等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
Bun145,000
Deno85,000
Node.js65,000

同样的硬件,Bun每秒多处理8万个请求。放到生产环境里,这意味着你可以少开几台服务器,每个月少交一笔不小的云服务费。

包安装速度(大型Remix项目):

工具安装时间
Bun8秒
npm3分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里调了半天的loaderplugin,那些搜了一圈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++原生模块的包。如果你的项目里有sharpbcrypt这类包,需要单独测试一下兼容性。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需要确保它的长期稳定。

对普通开发者来说,这意味着两件事:

  1. Bun不会死。 有了大厂的资金支持,Bun的长期维护不用担心。
  2. 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包上(比如bcryptsharp)。建议先在开发环境跑一遍测试套件,确认没问题再往生产环境推。