5月28日 02:46

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+BigIntPromise.allSettledOptional Chaining?.)、Nullish Coalescing??)——这些已经是基础能力,三个主流运行时都支持。

ES2022-2023Array.at()Object.hasOwn()、Top-level awaitArray.findLast()Array.toSorted() / toReversed() / toSpliced()——注意 toSorted 这类非变异方法在函数式编程中很实用,Bun 开箱即用。

ES2024-2025Promise.withResolvers()Object.groupBy()Map.groupBy()String.isWellFormed()、正则表达式 /v 标志。Bun v1.3.10 起完整支持 TC39 Stage 3 的 ES Decorators 标准规范,包括 accessor 关键字、Symbol.metadataClassFieldDecoratorContext API——不再只是 TypeScript 的 experimentalDecorators,而是语言层面的装饰器。

模块系统:原生 ESM,import / export 直接可用,同时也兼容 CommonJS 的 require()——Bun 会自动处理两种模块系统的互导,不需要 .mjs / .cjs 扩展名区分。

Web APIfetchWebSocketURLURLSearchParamsTextEncoder / TextDecoderReadableStreamAbortController 等浏览器 API 全部内置,写服务端代码时不再需要 node-fetch 这类 polyfill。

TypeScript 特性

Bun 内置 TypeScript 支持,.ts / .tsx 文件直接 bun run 即可执行,转译速度约 10ms:

  • 类型系统完整:泛型、类型守卫、条件类型、映射类型、模板字面量类型全部支持
  • JSX / TSX:零配置支持,React 项目不需要配置 Babel
  • 装饰器双模式:同时支持 TC39 标准 ES Decorators 和 TypeScript 的 experimentalDecorators(在 tsconfig.json 中配置)
  • 路径别名tsconfig.jsonpaths 配置自动生效,不用装 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 写查询,自带参数化防注入:

typescript
import { 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 的关键差异

方面BunNode.js
JS 引擎JavaScriptCoreV8
TS 支持内置,零配置v22.6+ 实验性支持
ESM原生优先,兼容 CJSCJS 优先,ESM 需配置
包管理器bun installnpm / 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++ 原生模块跑不了——bcryptbcryptjscanvas 看看能不能用 sharp 替代;2) process.env 读取时机——Bun 的 env 注入方式略有不同,某些在模块顶层读环境变量的代码可能行为不一致;3) __dirname__filename——Bun 中推荐用 import.meta.dirimport.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 文件中使用。这个差异在迁移时最容易被忽略。

标签:Bun