# Deno vs Node.js vs Bun

这是一个按维度做决策的对比，不是跑分榜。三个运行时都在快速演进：兼容性声明、默认行为和性能结论都可能随版本变化。本页只写已在官方来源核实的声明，并标注核实日期。

## 分维度对比

| 维度 | 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` 单文件二进制 |

## 性能：不要引用别人的跑分

本页不列具体数字，因为公开基准对硬件、版本、负载形态高度敏感，且各方发布的数字通常选择对自己有利的场景。正确的做法是测量自己的负载：

1. 固定运行时与依赖版本（`deno --version`、`node --version`、`bun --version` 记录进报告）。
2. 在同一台机器、同一数据集上运行；包含启动时间、稳态吞吐、p50/p99 延迟与常驻内存。
3. 区分微基准（JSON 序列化、Hello World）与真实路径（框架中间件、数据库驱动、TLS）。前者很少预测后者。
4. 对启动敏感的场景（CLI、冷启动）与长驻服务分开测量。
5. 把结果连同版本、OS/arch、命令一起存档，升级后重跑再对比。

## 何时选谁

| 约束 | 倾向 |
| --- | --- |
| 维护现有 Node 生产系统；招聘、培训、托管支持优先 | Node.js |
| 新项目；TypeScript 优先；希望 fmt/lint/test/编译零配置；需要默认拒绝的权限沙箱 | Deno |
| 发布 TypeScript 库并希望 Deno/Node 双运行时消费 | Deno + JSR |
| 对安装与启动速度敏感，且愿意用真实测试自行验证 npm 兼容 | Bun |
| 已有 Node 项目，想渐进评估或迁移到 Deno | 先读[从 Node.js 迁移](/docs/migration/from-node) |

没有普适答案。把上表当作排除工具：先用硬约束（权限、托管、既有代码、团队经验）删掉不合适的选项，再对剩余选项跑自己的基准。

<Callout type="warn" title="兼容性声明按版本核实">
"X 兼容 Y" 是版本敏感的声明。Bun 的兼容表对齐特定 Node 版本并持续更新，Deno 的 Node 兼容细节也在小版本间演进。落地前用项目的真实依赖与测试套件验证，不要依赖任何单页对比（包括本页）。
</Callout>

官方来源：[Deno 2.0 发布说明](https://deno.com/blog/v2.0)、[Deno Node 兼容文档](https://docs.deno.com/runtime/fundamentals/node/)、[Node.js TypeScript 支持](https://nodejs.org/api/typescript.html)、[Node.js 权限模型](https://nodejs.org/api/permissions.html)、[Bun Node.js 兼容表](https://bun.sh/docs/runtime/nodejs-apis)、[Bun TypeScript 文档](https://bun.sh/docs/runtime/typescript)。
