Bun 能跑你的 TypeScript 项目吗?特性兼容性详解
Bun 基于 JavaScriptCore 引擎(Safari 同款),原生支持运行 JavaScript 和 TypeScript,不需要 Babel、tsc 或任何转译工具。它覆盖了 ES2020 至 ES2025 的全部 ECMAScript 标准,兼容约 98% 的 Node.js API,绝大多数 Node 项目直接 bun run 就能跑。
JavaScript 特性
Bun 的 JS 引擎紧跟 Safari 的 JavaScriptCore 更新,当前版本支持到 ES2025 全部稳定特性:
ES2020+:BigInt、Promise.allSettled、Optional Chaining(?.)、Nullish Coalescing(??)——这些已经是基础能力,三个主流运行时都支持。
ES2022-2023:Array.at()、Object.hasOwn()、Top-level await、Array.findLast()、Array.toSorted() / toReversed() / toSpliced()——注意 toSorted 这类非变异方法在函数式编程中很实用,Bun 开箱即用。
ES2024-2025:Promise.withResolvers()、Object.groupBy()、Map.groupBy()、String.isWellFormed()、正则表达式 /v 标志。Bun v1.3.10 起完整支持 TC39 Stage 3 的 ES Decorators 标准规范,包括 accessor 关键字、Symbol.metadata 和 ClassFieldDecoratorContext API——不再只是 TypeScript 的 experimentalDecorators,而是语言层面的装饰器。
模块系统:原生 ESM,import / export 直接可用,同时也兼容 CommonJS 的 require()——Bun 会自动处理两种模块系统的互导,不需要 .mjs / .cjs 扩展名区分。
Web API:fetch、WebSocket、URL、URLSearchParams、TextEncoder / TextDecoder、ReadableStream、AbortController 等浏览器 API 全部内置,写服务端代码时不再需要 node-fetch 这类 polyfill。
TypeScript 特性
Bun 内置 TypeScript 支持,.ts / .tsx 文件直接 bun run 即可执行,转译速度约 10ms:
- 类型系统完整:泛型、类型守卫、条件类型、映射类型、模板字面量类型全部支持
- JSX / TSX:零配置支持,React 项目不需要配置 Babel
- 装饰器双模式:同时支持 TC39 标准 ES Decorators 和 TypeScript 的
experimentalDecorators(在tsconfig.json中配置) - 路径别名:
tsconfig.json的paths配置自动生效,不用装tsconfig-paths - 枚举和命名空间:TypeScript 独有语法,Bun 全部支持,无需
isolatedModules限制
一个关键区别:Bun 只做转译,不做类型检查。这意味着类型错误不会阻止代码运行——开发时靠 IDE 实时提示,CI 中用 tsc --noEmit 做类型检查。这是刻意的设计选择,用 10ms 的转译速度换取开发体验。
推荐的 tsconfig.json 配置:
json{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "types": ["bun-types"] } }
安装类型定义:bun add -d @types/bun,这样 Bun.file()、Bun.serve() 等 API 都有完整的类型提示。
Bun 独有 API
Bun 不只是"另一个 Node.js",它提供了一套更简洁的原生 API,很多是 Node.js 需要装第三方包才能实现的能力:
文件操作 — Bun.file(path) 返回一个 Blob 引用(不立即读内存),Bun.write(path, content) 写入文件。比 fs.readFile 快 3-10 倍,因为底层用了更高效的系统调用。
HTTP 服务器 — Bun.serve() 内置 HTTP/1.1、HTTP/3 QUIC、WebSocket、SSE 支持,Bun 1.3 起还支持前端热重载。一个函数搞定 API 服务 + 静态文件 + WebSocket。
数据库 — Bun.SQL 是统一的 SQL 客户端,支持 Postgres、MySQL、MariaDB、SQLite,零外部依赖。用 tagged template literal 写查询,自带参数化防注入:
typescriptimport { sql } from "bun"; const users = await sql`SELECT * FROM users WHERE id = ${userId}`;
对象存储 — Bun.S3Client 内置 S3 兼容操作,支持上传、下载、列表、存储类配置。
测试 — bun test 是 Jest 兼容的测试运行器,速度是 Jest 的 5-20 倍,支持快照测试、并行执行、JUnit 报告输出。
和 Node.js 的关键差异
| 方面 | Bun | Node.js |
|---|---|---|
| JS 引擎 | JavaScriptCore | V8 |
| TS 支持 | 内置,零配置 | v22.6+ 实验性支持 |
| ESM | 原生优先,兼容 CJS | CJS 优先,ESM 需配置 |
| 包管理器 | bun install | npm / yarn / pnpm |
| 测试 | 内置 bun test | 需安装 Jest / Vitest |
| HTTP 服务器 | 内置 Bun.serve() | 需安装 Express / Fastify |
| 数据库客户端 | 内置 | 需安装 pg / mysql2 |
| Node API 兼容 | ~98% | 原生 |
| 长时间运行 GC | 较新,仍在优化 | V8 GC 成熟稳定 |
不兼容的场景:原生 C++ addon(node-gyp)因为引擎不同无法直接运行——canvas(依赖 cairo)、better-sqlite3(依赖 node-gyp)这类包需要找纯 JS 替代或等 Bun 的原生方案。Bun 1.3 已经内置了 SQLite 客户端,better-sqlite3 的场景可以直接用 Bun.SQL 替代。
追问
Bun 的 TS 支持和 Deno 有什么区别?
两者都原生支持 TS。核心区别:Bun 追求 Node.js 兼容和速度,只做转译不做类型检查;Deno 可以做运行时类型检查(deno check),而且有权限安全模型。从 Node 迁移选 Bun(兼容性好),从零开始重视安全选 Deno。实际开发中两者都能跑主流框架,选哪个更多取决于团队偏好。
迁移 Node 项目到 Bun 踩过什么坑?
三个最常见的坑:1) C++ 原生模块跑不了——bcrypt 换 bcryptjs,canvas 看看能不能用 sharp 替代;2) process.env 读取时机——Bun 的 env 注入方式略有不同,某些在模块顶层读环境变量的代码可能行为不一致;3) __dirname 和 __filename——Bun 中推荐用 import.meta.dir 和 import.meta.file 替代,CJS 兼容模式下也能用但 ESM 下不行。迁移前跑一遍 bun test,全过再切 bun run。
Bun 适合生产环境吗?
2026 年可以了。Bun 通过了 90%+ 的 Node.js 测试套件,Anthropic 2025 年底收购后投入加大,Vercel 已认证 Bun 平台,约 20% 的新 Next.js 部署跑在 Bun 上。但如果你的服务是 72 小时+的长驻进程,V8 的 GC 在这类场景更成熟,建议压测后再决定。
为什么 Bun 比 Node.js 快?
三个原因:JavaScriptCore 引擎启动更快(牺牲了一点 JIT 长期优化换启动速度);核心模块用 Zig 写,减少了 JS/C++ 边界调用开销;模块解析用全局缓存,不用每次遍历 node_modules 查找。结果就是"启动"和"IO 密集"场景优势最大(包安装快 10-30 倍、HTTP 吞吐量 2-3 倍),纯 CPU 计算和 Node 差距不大。
Bun 和 Node.js 的 ESM 处理有什么不同?
Bun 原生 ESM 优先——import 语句直接解析,不需要 package.json 加 "type": "module",也不需要 .mjs 扩展名。require() 在 Bun 的 ESM 文件中也能用(Bun 自动处理互导)。Node.js 则是 CJS 优先,ESM 需要显式配置,而且 require() 不能在 ESM 文件中使用。这个差异在迁移时最容易被忽略。