从 Node.js 迁移

以可回滚、可验证的阶段把现有 Node.js 项目迁到 Bun

最后更新于

推荐策略:并行采用

不要在一个提交里同时替换运行时、包管理器、测试和打包器。每多替换一个边界,定位问题的成本都会上升。

阶段改动通过条件回滚
1. 本地脚本用 Bun 跑独立工具脚本输出与 Node 一致保留 node script.js
2. 包管理生成 bun.lock冻结安装、测试、构建通过保留旧锁文件到评审完成
3. 测试迁移一组单测结果和覆盖率可接受原 runner 仍可运行
4. 开发运行时本地服务用 Bun集成测试通过旧 dev 脚本可用
5. 生产运行时改容器 / 入口预发布压测和回滚演练通过可切回旧镜像

迁移进度清单

已完成 0 / 5

进度只保存在当前浏览器,不会上传。

迁移前盘点

rg "node:|process\.|__dirname|require\(|worker_threads|child_process" src
bun pm ls

重点检查:

  • .node 原生扩展;
  • 自定义 ESM loader、require hook 或 Babel transformer;
  • 依赖 Node/V8 特定诊断行为的工具;
  • Jest 专属环境、插件和 fake timers;
  • 框架官方支持矩阵与部署平台运行时。

包管理迁移

bun install
bun install --frozen-lockfile

Bun 在没有 bun.lock 时可迁移现有锁文件。先审查生成结果并跑全套验证,不要立即删除原锁文件。切换获批后,只保留一个权威锁文件。

Docker 基线

FROM oven/bun:1 AS install
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile

FROM oven/bun:1 AS release
WORKDIR /app
COPY --from=install /app/node_modules ./node_modules
COPY . .
ENV NODE_ENV=production
USER bun
CMD ["bun", "run", "start"]

真实项目应使用 .dockerignore、按框架复制构建产物,并固定经组织验证的镜像版本或 digest。

验收矩阵

  • 类型检查、单元、集成、端到端测试;
  • 冷启动、吞吐、内存和长时间稳定性;
  • SIGTERM 优雅退出;
  • 时区、Unicode、文件路径和大小写;
  • TLS、代理、数据库连接池与 DNS;
  • 容器平台的 CPU 架构和 libc 差异;
  • 可观测性 Agent 和 sourcemap。

建立双运行时兼容 CI

迁移期间对同一组纯业务和集成测试分别运行 Node 与 Bun,把差异变成可观察证据:

strategy:
  matrix:
    runtime: [node, bun]

真实工作流应让 Node Job 使用组织支持的 Node 版本和原包管理流程,让 Bun Job 固定验证过的 Bun 版本。比较退出码、HTTP 契约、数据库行为和构建产物,不要求两个运行时的内部日志或性能数字完全相同。只有 Bun 路径通过全部发布门禁后才移除 Node 回滚路径。

兼容性必须实测

“Node.js-compatible” 是迁移起点,不是项目验收结果。依赖树、框架版本和生产平台共同决定是否可切换。