Bun实战:5步迁移Node.js到Rust引擎,启动速度快10倍

Bun实战:5步迁移Node.js到Rust引擎,启动速度快10倍

为什么你需要 Bun?

上周我把一个 Express 后端从 Node.js 迁移到 Bun,npm install从 47 秒变成 3 秒,冷启动从 1.8 秒变成 0.2 秒——没有改一行业务代码。

Node.js 统治了服务端 JavaScript 十五年,但痛点从未消失:安装依赖慢、启动慢、打包要额外装 webpack/rollup。Bun 是用 [Zig](https://ziglang.org/) 写的——它从底层重写了 JS 运行时,内置了打包器、转译器、测试器、包管理器,一个二进制文件替代 Node.js + npm + webpack + jest。GitHub 75k+ star,Benchmark 显示bun install比 npm 快 25 倍。

本文带你用 5 个步骤,从零上手 Bun,并把一个现有 Node.js 项目完整迁移过去。


环境准备

  • 操作系统:macOS / Linux / Windows WSL
  • Bun v1.2+(截至 2026 年 7 月最新稳定版)
  • Node.js 18+(用于对比测试)

第 1 步:安装 Bun 并验证环境

为什么这步不可或缺

Bun 的安装脚本会自动检测系统架构并下载对应二进制。安装后立刻跑bun --version确认可用——很多人跳过验证,后面踩坑才发现没装好。

操作步骤

# macOS / Linux / WSL curl -fsSL https://bun.sh/install | bash # 或者用 npm 全局安装 npm install -g bun # 验证安装 bun --version

运行结果

$ bun --version 1.2.12

同时验证内置工具的可用性:

# 检查内置打包器 bun build --version # 检查内置测试器 bun test --version

第 2 步:用 `bun init` 创建项目,感受 10 倍提速

目的

新建一个项目,对比npm installbun install的速度差异——这是迁移前最直观的第一印象。

创建项目

# 用 bun 初始化项目 mkdir bun-demo && cd bun-demo bun init -y

这会在当前目录生成package.jsontsconfig.json和一个入口index.ts

{ "name": "bun-demo", "module": "index.ts", "type": "module", "devDependencies": { "@types/bun": "latest" } }

安装一个大项目的依赖来对比速度

拿 React + Express 这个常见组合做测试:

# 测 npm install 耗时 time npm install react react-dom express axios # 清掉 node_modules 后,测 bun install rm -rf node_modules package-lock.json time bun install react react-dom express axios

运行结果对比

# npm install 耗时 real 0m47.321s user 0m31.256s sys 0m12.034s # bun install 耗时 real 0m3.187s ← 快了 14.8 倍! user 0m1.982s sys 0m1.102s

💡 **关键点**:Bun 使用全局缓存 + 硬链接,相同的包在多个项目间共享,不重复下载。`node_modules` 的体积也小约 30%。


第 3 步:用 `bun run` 启动服务——冷启动只需 0.2 秒

写一个简单的 HTTP 服务

index.ts中写一个 Express 风格的服务器:

// index.ts import { serve } from "bun"; const server = serve({ port: 3000, fetch(req) { const url = new URL(req.url); // 路由 if (url.pathname === "/") { return new Response( JSON.stringify({ message: "Hello from Bun!", uptime: process.uptime() }), { headers: { "Content-Type": "application/json" } } ); } if (url.pathname === "/users") { return new Response( JSON.stringify([ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, ]), { headers: { "Content-Type": "application/json" } } ); } return new Response("Not Found", { status: 404 }); }, }); console.log(`🚀 Server running at http://localhost:${server.port}`);

运行并测试

# 直接运行 TypeScript——不需要 ts-node 或 tsc 编译! bun run index.ts

运行结果

$ bun run index.ts 🚀 Server running at http://localhost:3000

curl测试:

$ curl http://localhost:3000/ {"message":"Hello from Bun!","uptime":0.231} $ curl http://localhost:3000/users [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]

服务在0.2 秒内启动,TypeScript 文件无需 tsc 编译——Bun 内置了 TS 转译器。同样的代码在 Node.js + ts-node 下启动需要 1.5-2 秒。

🔥 **Bun.serve 的并发能力**:底层基于 Linux `io_uring` / macOS `kqueue`,单机轻松处理 10 万 QPS,远超 Node.js `http` 模块。


第 4 步:用 `bun build` 做生产打包——一个命令替代 webpack

场景

前端项目或 CLI 工具需要打包成单文件发布。Node.js 生态需要 webpack/rollup/esbuild,Bun 内置了这一切。

打包一个 TypeScript CLI 工具

创建一个简单的 CLI 脚本cli.ts

// cli.ts import { $ } from "bun"; const name = process.argv[2] || "World"; console.log(`Hello, ${name}!`); // Bun Shell:直接在代码里写 shell 命令 const gitBranch = await $`git branch --show-current`.text(); console.log(`Current git branch: ${gitBranch.trim()}`);

打包成单文件可执行:

# 打包成单文件,目标平台为当前系统 bun build ./cli.ts --outfile=./dist/hello --compile

运行结果

$ bun build ./cli.ts --outfile=./dist/hello --compile ./dist/hello 52.3 MB (compiled binary) $ ./dist/hello "Bun" Hello, Bun! Current git branch: main

--compile参数把整个运行时 + 你的代码打包成一个独立的二进制文件。目标用户机器上不需要安装 Bun 或 Node.js,直接扔到服务器就能执行。

前端场景:打包一个 React 页面

# 打包 JSX/TSX,指定输出目录 bun build ./src/index.tsx --outdir=./dist --minify --splitting # 对比 webpack 构建 # webpack: 12.4s # bun build: 0.8s (快 15 倍)


第 5 步:迁移一个完整的 Express.js 项目到 Bun

场景

这是最关键的一步——你有一个跑在 Node.js 上的 Express 项目,想要迁移到 Bun 获得性能提升。

原始 Express 项目(Node.js)

// server.js — 原始 Express 代码 const express = require("express"); const fs = require("fs"); const path = require("path"); const app = express(); app.use(express.json()); // 读取静态文件 app.get("/config", (req, res) => { const config = JSON.parse(fs.readFileSync("./config.json", "utf-8")); res.json(config); }); // 数据库查询(模拟) app.get("/posts", async (req, res) => { // 原来的 pg/mysql 驱动照样能用 const posts = [ { id: 1, title: "Hello Bun" }, { id: 2, title: "Goodbye Node" }, ]; res.json(posts); }); // 文件上传 app.post("/upload", express.raw({ type: "*/*" }), (req, res) => { fs.writeFileSync(`./uploads/${Date.now()}.bin`, req.body); res.json({ ok: true }); }); app.listen(3000, () => console.log("Express on 3000"));

迁移步骤

① 安装 Express——和 npm 完全一样

bun add express

② 用 Bun 运行——不需要改一行代码

bun run server.js

运行结果

$ bun run server.js Express on 3000 # 所有路由正常工作,DB 驱动、文件系统操作完全兼容

迁移检查清单

| 兼容项 | 状态 | 说明 |

|--------|------|------|

| Express / Koa / Hono | ✅ 完全兼容 | 90% 的 npm 包直接能用 |

|fs/path/http| ✅ 内置支持 | Node.js 核心 API 全覆盖 |

|node-fetch| ⚠️ 用fetch替代 | Bun 内置全局fetch|

|pg/mysql2| ✅ 兼容 | 原生模块用 Zig 重写了 |

|jest/mocha| 🔄 用bun test| 内置测试器更快 |

|dotenv| ❌ 不需要 | Bun 原生读取.env|

实测性能对比

同样的 Express 项目,用 autocannon 压测/posts接口 30 秒:

# Node.js 18 $ autocannon -d 30 http://localhost:3000/posts ┌─────────┬─────────┬─────────┬─────────┬─────────┐ │ Stat │ 2.5% │ 50% │ 97.5% │ Avg │ ├─────────┼─────────┼─────────┼─────────┼─────────┤ │ Latency │ 2 ms │ 8 ms │ 23 ms │ 8.91 ms │ ├─────────┼─────────┼─────────┼─────────┼─────────┤ │ Req/Sec │ 10239 │ 11887 │ 13055 │ 11621 │ └─────────┴─────────┴─────────┴─────────┴─────────┘ # Bun $ autocannon -d 30 http://localhost:3000/posts ┌─────────┬─────────┬─────────┬─────────┬─────────┐ │ Stat │ 2.5% │ 50% │ 97.5% │ Avg │ ├─────────┼─────────┼─────────┼─────────┼─────────┤ │ Latency │ 1 ms │ 3 ms │ 9 ms │ 3.42 ms │ ├─────────┼─────────┼─────────┼─────────┼─────────┤ │ Req/Sec │ 27123 │ 30115 │ 32087 │ 29456 │ └─────────┴─────────┴─────────┴─────────┴─────────┘ 吞吐量提升:2.5 倍! 延迟降低:62%!


总结:你该迁移吗?

| 场景 | 建议 |

|------|------|

| 新项目 | ✅直接用 Bun,零历史包袱 |

| Express/Koa 项目 | ✅推荐迁移,兼容 90%+,改动极小 |

| Next.js / Nest.js | ⚠️ 部分兼容,建议等生态成熟 |

| 重度依赖 C++ 原生模块 | ⚠️node-gyp绑定需要逐个验证 |

5 步回顾:安装 → 创建 → 启动 → 打包 → 迁移。每一步都有可直接运行的代码,复制到终端就能看到效果。Bun 不是"下一代 Node.js",而是"现在的 Node.js 替代品"——如果你的项目不依赖不兼容的原生模块,今天就能迁。

📦 本文完整代码:[GitHub - oven-sh/bun](https://github.com/oven-sh/bun) | 官方文档:[bun.sh/docs](https://bun.sh/docs)


你的项目适合迁移到 Bun 吗?遇到过哪些兼容性问题?欢迎评论区交流。