2026 年了,还在用 Node.js?Bun 迁移实战:20 分钟搞定,附踩坑记录

如果你的项目每次 npm install 要等一分钟,每次跑测试要等十几秒,每次启动开发服务器要盯着终端发呆------你应该试试 Bun。这篇文章不吹不黑,直接上手把一个真实项目从 Node.js 迁到 Bun,把迁移步骤、踩过的坑、适不适合你的项目全部写清楚。

Bun 是什么,为什么 2026 年该试试

如果你还不知道 Bun------它是一个用 Zig 语言写的 JavaScript 运行时,目标是做 Node.js 的替代品。

一句话总结它和 Node.js 的关系:

Bun 之于 Node.js,就像 Vite 之于 Webpack------做同样的事,但快得多。

它不只是一个运行时,而是一个全家桶:

功能 Node.js 生态 Bun 内置
运行时 Node.js Bun
包管理器 npm / pnpm / yarn bun install
打包器 Webpack / Vite / esbuild bun build
测试框架 Jest / Vitest bun test
TypeScript 需要 ts-node / tsx 原生支持,直接跑 .ts
.env 加载 需要 dotenv 包 原生支持

2026 年的 Bun 已经到了 1.2+ 版本,稳定性比两年前好了很多。大部分 npm 包都能直接用。


迁移前后数据对比

Bun 官方跑的 benchmark 和社区实测都指向同一个结论:快,而且不是快一点。

以一个中等规模的全栈项目(React + Express,约 200 个 npm 依赖)为参考:

操作 Node.js 20 + npm Bun 1.2 差距
install(无缓存) 约 40-60s 约 3-5s 10-15x
install(有缓存) 约 10-15s < 1s 20x+
开发服务器启动 约 5-10s 约 1-3s 3-5x
单测(100+ 用例) 约 10-15s 约 3-5s 3x
TypeScript 编译 需要额外配置 ts-node 原生支持 ---
冷启动一个 HTTP 接口 约 200-400ms 约 50-100ms 3-4x

具体数值取决于你的机器配置和项目大小,但量级差距是一致的。你可以在自己项目里跑一下对比看看。


迁移步骤(20 分钟搞定)

第一步:安装 Bun

bash 复制代码
# macOS / Linux
curl -fsSL https://bun.sh/install | bash

# 验证安装
bun --version
# 1.2.x

Windows 用户用 WSL2 安装。Bun 对 Windows 原生的支持在 1.2 版本已经基本完善。

第二步:用 Bun 替换 npm

bash 复制代码
# 删掉 node_modules 和 lock 文件
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml

# 用 Bun 重新安装依赖
bun install

这一步会生成 bun.lockb(Bun 的 lock 文件,二进制格式,比 JSON 快得多)。

第三步:替换 package.json 里的 scripts

json 复制代码
{
  "scripts": {
    "dev": "bun run --hot src/server.ts",
    "build": "bun build src/index.ts --outdir dist",
    "test": "bun test",
    "start": "bun src/server.ts"
  }
}

关键变化:

  • node src/server.jsbun src/server.ts(直接跑 TypeScript,不需要 ts-node)
  • nodemonbun run --hot(内置热重载)
  • jest / vitestbun test(内置测试框架,API 兼容 Jest)

第四步:测试跑一遍

bash 复制代码
bun test
bun run dev

大多数项目到这一步就可以正常跑了。如果遇到问题,看下面的踩坑记录。


踩坑记录

坑 1:某些 Node.js 原生模块不兼容

我的项目用了 bcrypt(密码哈希),它是 C++ 写的 native addon。Bun 对大部分 native addon 已经支持了,但 bcrypt 的某个版本有问题。

解决方案: 换成纯 JS 实现的 bcryptjs

bash 复制代码
bun remove bcrypt
bun add bcryptjs

代码改动只有 import 路径:

javascript 复制代码
// 之前
import bcrypt from 'bcrypt';

// 之后
import bcrypt from 'bcryptjs';

API 完全一致,不需要改业务代码。性能差距在大多数场景下可以忽略。

通用原则: 如果某个包有 C++ native addon 版本和纯 JS 版本,迁移到 Bun 时优先选纯 JS 版本。

坑 2:__dirname__filename 行为差异

Bun 支持 __dirname__filename,但在 ES Module 模式下行为和 Node.js 有细微差异。

如果你的代码里有这种写法:

javascript 复制代码
import path from 'path';
const configPath = path.join(__dirname, '../config/default.json');

在 Bun 的 ESM 模式下可能报错。

解决方案:import.meta 替代。

javascript 复制代码
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const configPath = path.join(__dirname, '../config/default.json');

这个写法同时兼容 Node.js 和 Bun。

坑 3:.env 不需要 dotenv 了

Bun 原生支持 .env 文件加载,不需要 dotenv 包。

如果你的代码里有:

javascript 复制代码
import 'dotenv/config';
// 或
require('dotenv').config();

在 Bun 里可以直接删掉这行。Bun 会自动加载项目根目录的 .env 文件。

但要注意:如果你同时有 .env.env.local,Bun 的加载优先级和 dotenv 不一样。 Bun 的优先级是:

bash 复制代码
.env.local > .env.production / .env.development > .env

建议:迁移后检查一下环境变量是否都正确加载了。

坑 4:bun test 和 Jest 的语法差异

bun test 的 API 和 Jest 基本兼容,但有几个地方不同:

javascript 复制代码
// Jest 写法(在 Bun 中也能跑)
expect(fn).toHaveBeenCalledWith(expect.objectContaining({ id: 1 }));

// 但这个 Jest 特有的 mock 方式不支持:
jest.mock('./database');

// Bun 的 mock 方式:
import { mock } from 'bun:test';
mock.module('./database', () => ({
  query: mock(() => Promise.resolve([]))
}));

解决方案: 如果你的测试大量依赖 jest.mock,建议暂时保留 Vitest 或 Jest 来跑测试,其他部分用 Bun。Bun 可以和现有测试框架共存。


哪些场景适合迁移,哪些不适合

场景 是否建议迁移 原因
个人项目 / side project ✅ 强烈推荐 没有历史包袱,直接享受速度
新项目 ✅ 推荐 从零开始用 Bun,避免迁移成本
中小型全栈项目 ✅ 可以 大部分 npm 包已兼容
大型企业项目 ⚠️ 谨慎 native addon 多,CI/CD 需要适配
依赖大量 native addon ❌ 暂不建议 sharp、canvas 等可能有兼容问题
Serverless / Edge 部署 ✅ 推荐 Bun 冷启动极快,适合 serverless

迁移检查清单

用这个清单确认迁移是否完整:

  • bun install 安装成功,无报错
  • bun run dev 开发服务器正常启动
  • bun test 测试全部通过
  • .env 环境变量正确加载
  • 所有 API 接口手动测试通过
  • 构建产物 bun build 正常输出
  • CI/CD 流水线里的 Node.js 镜像换成 Bun 镜像
  • Dockerfile 基础镜像改为 oven/bun:1.2
  • package.json 里的 scripts 都更新了
  • 删掉不再需要的包:dotenvts-nodenodemon

迁移后可以卸载的包

迁移到 Bun 后,这些包可以直接删掉:

bash 复制代码
bun remove dotenv ts-node tsx nodemon ts-jest
包名 原因
dotenv Bun 原生支持 .env
ts-node / tsx Bun 原生跑 TypeScript
nodemon bun run --hot 内置热重载
ts-jest bun test 原生支持 TypeScript

少了这些依赖,node_modules 又小了一圈。


写在最后

迁移整个项目大概 20 分钟,踩坑修复算上也就 1 个多小时。

换来的是每天开发过程中安装快十几倍、启动快好几倍、测试快 3 倍。这种速度差距体验过就回不去了。

如果你还在犹豫,建议先拿一个 side project 试试。20 分钟的迁移成本,几乎零风险。

你的项目目前用什么运行时和包管理器?有考虑过迁移到 Bun 吗?评论区聊聊。

相关推荐
青山Coding3 小时前
Cesium应用(八):物体运动的实现思路
前端·cesium
用户41659673693553 小时前
Android WebView 加载 file:// 离线页面调试教程
android·前端
Asmewill3 小时前
curl命令学习笔记一
前端
我是一只快乐的小螃蟹3 小时前
1.2 ArrayList 源码解析
前端
星栈3 小时前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:再把新建、编辑和交付补上
前端·rust·前端框架
我是一只快乐的小螃蟹3 小时前
1.1 HashMap (JDK1.8) 源码解析
前端
爱勇宝6 小时前
小红花成长新版:模板来了,鼓励也更容易开始
前端·后端·程序员
竹林8186 小时前
Solana前端开发:我在一个NFT铸造页面上被@solana/web3.js的Connection和Transaction签名坑了两天
前端
冬奇Lab6 小时前
每日一个开源项目(第144篇):ai-website-cloner-template - 一条命令、多 Agent 并行,把任意网站逆向成 Next.js 代码
前端·人工智能·开源