Deno vs Node.js vs Bun
按运行时模型、权限、TypeScript、包管理、工具链与部署形态对比三个 JavaScript 运行时并给出选型决策
这是一个按维度做决策的对比,不是跑分榜。三个运行时都在快速演进:兼容性声明、默认行为和性能结论都可能随版本变化。本页只写已在官方来源核实的声明,并标注核实日期。
分维度对比
| 维度 | Deno 2 | Node.js | Bun |
|---|---|---|---|
| 引擎与模型 | V8 + Rust;Web API 优先,URL 导入与 Deno.serve | V8 + libuv;node: 内置模块,生态事实标准 | JavaScriptCore + Zig;同时实现 Web API 与 Node API |
| 权限模型 | 默认拒绝,--allow-* 可按 host、路径、环境变量细化 | 默认完整权限;可选 --permission 模型(v20 引入,v23.5/v22.13 起不再是实验性),官方定位为 "seat belt" 而非安全边界 | 默认完整权限;本页未能在官方文档核实到对等的内置权限模型,选型前以当前 Bun 文档为准 |
| TypeScript | 原生执行,内置 deno check 做完整类型检查 | 默认 type stripping(v23.6/v22.18 起默认开启,v25.2/v24.12 标记稳定);仅 erasable syntax,不做类型检查,不支持 .tsx | 直接转译执行 TS;类型检查交给 tsc,官方推荐 tsconfig 含 noEmit |
| 包管理与注册表 | 原生支持 package.json、node_modules 与 npm workspaces;npm: 与 jsr: specifier;deno add/install/ci | npm registry 与 package.json 是生态基准;pnpm/yarn 经 Corepack 或包管理器自身安装(Node 25 起 Corepack 不再随 Node 分发) | 兼容 package.json/node_modules;bun install 为内置包管理器 |
| 工具链 | fmt、lint、check、test、bench、doc、compile 全部内置 | node:test、--watch 内置;格式化与 lint 依赖生态工具 | test、bunx、bundler、单文件编译内置 |
| Node 兼容现状 | node:/npm: specifier + package.json 支持;细节持续演进,用真实测试验证 | 参照物本身 | 官方以 Node 兼容为目标并维护逐模块兼容表:"If a package works in Node.js but doesn't work in Bun, we consider it a bug" |
| 生态与招聘 | 生态较小,npm 兼容降低切换成本 | 最大的包生态、托管支持与招聘市场 | 生态较小,npm 兼容降低切换成本 |
| 部署形态 | 容器/VM/serverless + Deno Deploy + deno compile 单文件二进制 | 容器/VM/serverless,托管支持最广 | 容器/VM + bun build --compile 单文件二进制 |
性能:不要引用别人的跑分
本页不列具体数字,因为公开基准对硬件、版本、负载形态高度敏感,且各方发布的数字通常选择对自己有利的场景。正确的做法是测量自己的负载:
- 固定运行时与依赖版本(
deno --version、node --version、bun --version记录进报告)。 - 在同一台机器、同一数据集上运行;包含启动时间、稳态吞吐、p50/p99 延迟与常驻内存。
- 区分微基准(JSON 序列化、Hello World)与真实路径(框架中间件、数据库驱动、TLS)。前者很少预测后者。
- 对启动敏感的场景(CLI、冷启动)与长驻服务分开测量。
- 把结果连同版本、OS/arch、命令一起存档,升级后重跑再对比。
何时选谁
| 约束 | 倾向 |
|---|---|
| 维护现有 Node 生产系统;招聘、培训、托管支持优先 | Node.js |
| 新项目;TypeScript 优先;希望 fmt/lint/test/编译零配置;需要默认拒绝的权限沙箱 | Deno |
| 发布 TypeScript 库并希望 Deno/Node 双运行时消费 | Deno + JSR |
| 对安装与启动速度敏感,且愿意用真实测试自行验证 npm 兼容 | Bun |
| 已有 Node 项目,想渐进评估或迁移到 Deno | 先读从 Node.js 迁移 |
没有普适答案。把上表当作排除工具:先用硬约束(权限、托管、既有代码、团队经验)删掉不合适的选项,再对剩余选项跑自己的基准。
官方来源:Deno 2.0 发布说明、Deno Node 兼容文档、Node.js TypeScript 支持、Node.js 权限模型、Bun Node.js 兼容表、Bun TypeScript 文档。