Bun 深度拆解:一个 JavaScript 运行时如何让 Claude Code 在 9 天内用 Rust 重写自己——从 Zig 到 Rust 的百万行 AI 工程实践全解析
2026 年 5 月 14 日,一条 PR #30412 被合并进 Bun 的主分支。超过 100 万行 Rust 代码、6755 次提交,几乎全部由 Claude Code 智能体在 9 天内生成完成。GitHub 页面直接被这百万行代码搞崩溃了。这不是一个普通的语言迁移故事——这是一个关于 AI 工程化、系统编程语言选型、JavaScript 运行时架构设计的深度技术案例。
一、为什么 Bun 要抛弃 Zig?
1.1 Bun 的前世今生
Bun 由 Jarred Sumner 于 2022 年创建,定位为"JavaScript 的全家桶"——集运行时、包管理器、打包器、测试运行器于一身。与 Node.js 使用 V8 引擎不同,Bun 选择了苹果开源的 JavaScriptCore(WebKit 的 JS 引擎),底层实现语言则选择了 Zig。
为什么选 Zig?Jarred Sumner 的理由很明确:
- 编译速度极快:Zig 的编译循环接近脚本语言,对快速迭代友好
- C ABI 天然兼容:与 C/C++ 互操作几乎零成本
- 二进制体积小:Zig 在产物体积控制上非常激进
- 不需要学习曲线陡峭的特性:Zig 语法极简,没有 Rust 的 borrow checker 那种"编译器时刻在背后盯着你"的压力
Bun 发展到 9 万 Star、每周下载量数十万次的规模后,Zig 的短板开始显现。
1.2 Zig 的代价:内存 Bug 成了慢性病
Bun 的核心是一个高性能 JavaScript 运行时,每天要处理数十亿次函数调用。在这种规模下,内存管理的任何微小缺陷都会被放大:
- 内存泄漏:多个长期存在的内存泄漏问题消耗了团队大量调试时间
- flaky 测试:不确定性 bug(往往是内存问题导致的)让 CI/CD 不稳定
- 安全漏洞风险:dangling pointer、buffer overflow 这类问题在 Zig 中需要开发者自己保证安全性
Jarred Sumner 在 X 上发的那条推文精准地描述了困境:
"Bun v1.3.14 将于明日发布。如果我们合并 Rust 重写版本,这将是 Zig 的最后一个版本。"
四年前选择了 Zig 做快速迭代,四年后发现维护成本远超预期。这是很多技术选型都会遇到的"甜蜜陷阱"——早期的选择优势,在项目规模扩大后变成了维护负担。
1.3 Rust 能解决什么?
Rust 的核心价值在于其所有权系统和借用检查器,能够在编译时捕获内存安全问题:
// Rust 的所有权系统在编译期杜绝了悬垂指针
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权转移给 s2
// println!("{}", s1); // 编译错误!s1 已经不再拥有数据
println!("{}", s2);
}
对于一个需要处理海量请求的 JavaScript 运行时来说,这种保障意味着:
- 不再需要花大量时间调试内存泄漏
- CI/CD 中的 flaky 测试大幅减少
- 安全漏洞从源头被堵住
但 Rust 也有代价:编译时间长、学习曲线陡峭、borrow checker 在某些场景下会拖慢开发节奏。这就是为什么 Bun 选择了一个非常特殊的迁移策略——让 AI 来做机械移植。
二、AI 重写的工程实践:9 天 100 万行
2.1 Claude Code 的角色
这次重写的核心工具是 Claude Code(Anthropic 的 AI 编程助手)。Jarred Sumner 的策略是:
- 保持架构不变:不改变 Bun 的架构设计和数据结构
- AI 做机械翻译:让 Claude Code 将 Zig 代码逐文件翻译为 Rust
- 人类做架构决策:团队负责审查 AI 生成的代码,确保架构合理性
这个策略的精妙之处在于:AI 擅长的是"模式匹配+翻译",而人类擅长的是"架构设计+判断"。把机械性工作交给 AI,人类专注于高价值决策。
2.2 重写的规模与数据
| 指标 | 数据 |
|---|---|
| 总代码量 | 超过 100 万行 Rust 代码 |
| 提交次数 | 6,755 次 |
| 耗时 | 9 天 |
| 费用 | 约 16.5 万美元(Claude API 调用费) |
| 测试通过率 | 99.8% |
| 二进制体积变化 | 缩小 3-8 MB |
PR #30412 的规模之大,直接导致 GitHub 页面无法加载。这在开源历史上是罕见的。
2.3 关键技术决策
这次迁移保持了两个关键不变:
相同的架构设计:Bun 依然使用极少的第三方库,依然不依赖 async Rust。这意味着重写不是推倒重来,而是"换皮不换骨"。
相同的数据结构:核心数据结构保持不变,只替换底层实现语言。这让重写可以被理解为"编译器层面的翻译",而非架构重构。
为什么不依赖 async Rust?这是一个深思熟虑的决策:
// Bun 的异步模型:基于 epoll/kqueue/io_uring 的事件循环
// 不使用 tokio 等 async 运行时
use std::os::unix::io::AsRawFd;
struct EventLoop {
epoll_fd: i32,
// 自己管理事件循环,不引入 async 运行时
}
impl EventLoop {
fn new() -> std::io::Result<Self> {
let epoll_fd = unsafe { libc::epoll_create1(0) };
Ok(Self { epoll_fd })
}
fn poll(&mut self) -> std::io::Result<()> {
let mut events = [libc::epoll_event { events: 0, u64: 0 }; 1024];
let n = unsafe {
libc::epoll_wait(self.epoll_fd, events.as_mut_ptr(), 1024, -1)
};
// 处理事件...
Ok(())
}
}
不使用 async Rust 的好处:
- 避免了 async 生态的碎片化问题
- 保持了与 Zig 版本相同的事件循环模型
- 二进制体积更小(不需要引入 tokio 等大型依赖)
2.4 unsafe 代码的安全争议
一个值得关注的点是:100 万行 Rust 代码中包含了超过 1 万个 unsafe 代码块。这引发了社区的安全争议。
批评者认为:如果你写了那么多 unsafe 代码,那用 Rust 的意义何在?Rust 的核心价值——编译期内存安全——在 unsafe 块中是失效的。
Jarred Sumner 的回应很务实:
"unsafe 代码主要集中在 FFI(外部函数接口)层面,用于与 JavaScriptCore 引擎交互。这部分代码在 Zig 中也是 unsafe 的。Rust 的价值在于:非 FFI 部分获得了完整的编译期安全保证,而 FFI 部分至少有了明确的
unsafe标记,让审查者知道哪些代码需要额外关注。"
这是一个工程上的务实选择:不是追求 100% 的安全性,而是最大化安全性收益与工程成本的比值。
三、JavaScript 运行时的架构深度拆解
3.1 Bun 的核心架构
要理解这次重写的意义,需要先理解 Bun 的架构:
┌─────────────────────────────────────────────┐
│ 用户代码 │
│ (JavaScript/TypeScript) │
├─────────────────────────────────────────────┤
│ Bun API 层 │
│ (HTTP Server, File I/O, SQLite, etc.) │
├─────────────────────────────────────────────┤
│ JavaScript 引擎层 │
│ (JavaScriptCore / WebKit) │
├─────────────────────────────────────────────┤
│ 系统调用抽象层(Zig/Rust) │
│ (epoll/kqueue/io_uring, 文件系统等) │
├─────────────────────────────────────────────┤
│ 操作系统 │
│ (Linux, macOS, Windows) │
└─────────────────────────────────────────────┘
重写主要发生在系统调用抽象层——这一层负责与操作系统交互,包括事件循环、文件 I/O、网络 I/O、进程管理等。JavaScript 引擎层(JavaScriptCore)是苹果的代码,不需要重写。
3.2 事件循环:JavaScript 运行时的心脏
事件循环是 JavaScript 运行时最核心的组件。Bun 的事件循环设计:
// Bun 的事件循环简化示意
pub struct EventLoop {
// io_uring 实例(Linux)
io_uring: Option<IoUring>,
// epoll 实例(macOS)
epoll_fd: Option<i32>,
// 定时器堆
timers: BinaryHeap<Timer>,
// 待处理的 I/O 回调
pending_callbacks: VecDeque<Box<dyn FnOnce()>>,
}
impl EventLoop {
pub fn run(&mut self) {
loop {
// 1. 执行所有微任务(Promise 回调等)
self.run_microtasks();
// 2. 检查定时器
self.process_timers();
// 3. 轮询 I/O 事件
let events = self.poll_io();
// 4. 执行 I/O 回调
for event in events {
self.execute_callback(event);
}
// 5. 如果没有待处理事件,退出
if self.is_idle() {
break;
}
}
}
}
这个事件循环的 Rust 实现相比 Zig 版本的优势:
- 所有权系统确保回调函数不会在执行后被意外使用
- 借用检查器防止事件循环在遍历时被修改
VecDeque和BinaryHeap的内存管理由 Rust 自动处理
3.3 JavaScriptCore 的 FFI 层
Bun 的核心创新之一是直接使用 JavaScriptCore(JSC)而非 V8。与 JSC 的交互需要通过 FFI 层:
// 与 JavaScriptCore 的 FFI 交互
use std::ffi::CStr;
extern "C" {
fn JSContextCreate() -> *mut JSGlobalContextRef;
fn JSEvaluateScript(
ctx: *mut JSGlobalContextRef,
script: *const c_char,
thisObject: *const c_void,
sourceURL: *const c_void,
startingLineNumber: c_int,
exception: *mut *mut c_void,
) -> *const c_void;
}
pub struct JscContext {
raw: *mut JSGlobalContextRef,
}
impl JscContext {
pub fn new() -> Self {
let raw = unsafe { JSContextCreate() };
Self { raw }
}
pub fn evaluate(&self, script: &str) -> Result<String, EvalError> {
let c_script = CString::new(script).map_err(|_| EvalError::InvalidScript)?;
let result = unsafe {
JSEvaluateScript(
self.raw,
c_script.as_ptr(),
std::ptr::null(),
std::ptr::null(),
0,
std::ptr::null_mut(),
)
};
// 转换结果...
Ok(result_string)
}
}
impl Drop for JscContext {
fn drop(&mut self) {
unsafe {
// JSContextRelease 会在析构时自动调用
JSContextRelease(self.raw);
}
}
}
Drop trait 的实现是 Rust 的核心优势之一——它确保了 JavaScript 上下文在离开作用域时一定会被释放,这在 Zig 中需要开发者手动管理。
3.4 文件系统与网络 I/O
Bun 的文件系统操作使用了现代 Linux 的 io_uring 和 macOS 的 kqueue:
// io_uring 异步文件 I/O
#[cfg(target_os = "linux")]
pub struct IoUring {
ring: io_uring::IoUring,
}
#[cfg(target_os = "linux")]
impl IoUring {
pub fn new() -> io::Result<Self> {
let ring = io_uring::IoUring::new(256)?;
Ok(Self { ring })
}
pub async fn read_file(&self, path: &str) -> io::Result<Vec<u8>> {
let file = std::fs::File::open(path)?;
let fd = file.as_raw_fd();
let mut buf = vec![0u8; 4096];
let mut sqe = self.ring.submission().available();
sqe.prep_read(fd, &mut buf, 0);
self.ring.submit().await?;
Ok(buf)
}
}
// macOS kqueue 事件循环
#[cfg(target_os = "macos")]
pub struct Kqueue {
fd: i32,
}
#[cfg(target_os = "macos")]
impl Kqueue {
pub fn new() -> io::Result<Self> {
let fd = unsafe { libc::kqueue() };
if fd < 0 {
return Err(io::Error::last_os_error());
}
Ok(Self { fd })
}
pub fn add_event(&self, fd: i32, event_type: u16) -> io::Result<()> {
let mut kevent: libc::kevent = unsafe { std::mem::zeroed() };
kevent.ident = fd as _;
kevent.filter = event_type as i16;
kevent.flags = libc::EV_ADD | libc::EV_ENABLE;
unsafe {
libc::kevent(
self.fd,
&kevent,
1,
std::ptr::null_mut(),
0,
std::ptr::null(),
);
}
Ok(())
}
}
四、性能对比与基准测试
4.1 Zig 版 vs Rust 版
Jarred Sumner 在公告中表示,Rust 版本在所有平台上均达到或超越原有性能水平。具体数据:
| 测试项 | Zig 版 | Rust 版 | 变化 |
|---|---|---|---|
| HTTP 请求吞吐量 | 基准 | +2~5% | ✅ 提升 |
| 文件 I/O 速度 | 基准 | +3~8% | ✅ 提升 |
| 启动时间 | 基准 | -5~10% | ✅ 更快 |
| 二进制体积 | ~50 MB | ~45 MB | ✅ 缩小 3-8 MB |
| 内存占用 | 基准 | -10~15% | ✅ 更省 |
性能提升的原因:
- Rust 编译器的优化能力比 Zig 更成熟
- 所有权系统减少了不必要的内存拷贝
- 借用检查器帮助编译器做出更好的优化决策
4.2 与 Node.js 的性能对比
Bun 一直以"比 Node.js 快"为卖点。Rust 重写后,这个优势进一步扩大:
// Bun 的 HTTP 服务器
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello from Bun!");
},
});
基准测试数据(单核,1000 并发连接):
- Bun (Rust 版):~120,000 req/sec
- Bun (Zig 版):~115,000 req/sec
- Node.js 22:~35,000 req/sec
- Deno 2:~45,000 req/sec
Bun 的 HTTP 性能是 Node.js 的 3 倍以上,这得益于:
- 使用系统原生的 I/O 多路复用(io_uring/kqueue)
- 自研的 HTTP 解析器(不依赖 llhttp)
- JavaScriptCore 的 JIT 编译优化
4.3 包安装速度
Bun 的另一个核心卖点是包安装速度:
# Bun 包安装
$ bun install
# 典型时间:0.5-2 秒
# npm 包安装
$ npm install
# 典型时间:15-60 秒
Bun 的包安装速度是 npm 的 20-30 倍,这是因为:
- 全局缓存机制:相同包只下载一次
- 并行下载:多连接同时下载依赖
- 原生二进制解压:不依赖 Node.js 的 JS 解压逻辑
Rust 重写后,包安装的 I/O 层获得了更好的性能,安装速度进一步提升。
五、AI 工程化的启示
5.1 这次重写的真正意义
Bun 的 Rust 重写不仅仅是一个技术决策,它标志着 AI 工程化进入了一个新阶段:
从"AI 辅助编程"到"AI 主导机械工作":
传统模式:人类写代码,AI 辅助补全
Bun 模式:AI 做机械翻译,人类做架构决策
这种模式的前提是:
- 代码有明确的翻译规则(Zig → Rust 的语法映射)
- 有完善的测试套件验证正确性(99.8% 通过率)
- 架构保持不变,AI 只做"换皮"工作
5.2 AI 代码的质量争议
社区对这次重写的质疑集中在几个方面:
质疑 1:99.8% 测试通过率够吗?
对于一个运行时项目来说,0.2% 的测试失败意味着每 500 个测试就有 1 个失败。在生产环境中,这可能导致难以追踪的 bug。
但换个角度看:99.8% 的通过率是在9 天内达到的,而如果由人类团队来做同样的迁移,可能需要数月甚至数年时间。在那个时间窗口内,Bun 可能已经失去了市场竞争力。
质疑 2:1 万个 unsafe 块安全吗?
unsafe 代码确实绕过了 Rust 的安全检查。但这些 unsafe 代码主要集中在 FFI 层,与操作系统和 JavaScriptCore 交互。这部分代码在 Zig 中同样是 unsafe 的——Rust 至少让这些 unsafe 代码有了明确的标记。
质疑 3:AI 生成的代码可维护吗?
这是最实际的问题。AI 生成的代码是否符合 Rust 的惯用写法?是否遵循了项目的代码风格?后续维护是否困难?
Jarred Sumner 的回应是:团队对 AI 生成的代码进行了审查,确保了代码质量和风格一致性。但长期可维护性仍需时间验证。
5.3 对其他项目的启示
Bun 的案例为其他大型开源项目提供了参考:
适合 AI 重写的场景:
- 有完善的测试套件
- 代码有明确的翻译规则
- 架构不需要大规模调整
- 维护成本已经成为项目瓶颈
不适合 AI 重写的场景:
- 需要架构重构
- 缺乏测试覆盖
- 代码逻辑高度复杂
- 安全要求极高(如加密库)
六、Vercel 的反向操作:ZeroNative 与 Zig
有趣的是,在 Bun 投奔 Rust 的同一周,Vercel 旗下的 vercel-labs 放出了一个新项目 ZeroNative——用 Zig 构建跨端应用框架。
6.1 ZeroNative 是什么
ZeroNative 的定位是:用前端框架写 UI,底层跑在 Zig 写的 native runtime 上,打包成桌面和移动应用。对标的不是 Electron,而是 Tauri。
核心特性:
- 壳是 Zig 写的,74.6% 代码是 Zig
- 支持 macOS、Linux、Windows、iOS、Android
- WebView 引擎可选:WKWebView、WebKitGTK、WebView2 或 Chromium
- 安全模型借鉴了现代沙箱思路
6.2 为什么 Vercel 选 Zig 不选 Rust
Vercel 一直是 Rust 的深度用户(Turbopack、Turborepo、SWC 都是 Rust 写的)。但 ZeroNative 选了 Zig,理由是:
- 二进制更小:桌面和移动应用对包体积敏感
- 编译更快:Zig 的编译循环比 Rust 短得多
- C ABI 集成更顺滑:跨平台胶水代码用 Zig 写更自然
- 不需要 borrow checker:桌面壳的主要工作是窗口管理和 IPC,borrow checker 的收益有限
6.3 同一特性的两面
讽刺的是,Bun 想要 Rust 的 borrow checker 来解决内存问题,而 Vercel 想要 Zig 的简洁来加速迭代。同样的语言特性,在不同场景下被解读为优点或负担:
| 场景 | Rust 的 borrow checker | Zig 的简洁 |
|---|---|---|
| 高性能运行时 | ✅ 内存安全保障 | ❌ 需要手动管理 |
| 桌面/移动应用壳 | ❌ 开发节奏拖慢 | ✅ 快速迭代 |
| 大型开源项目 | ✅ 长期可维护性 | ❌ 维护成本高 |
| 小型工具 | ❌ 过度工程化 | ✅ 轻量简洁 |
这是工程决策最真实的样子:脱离场景谈语言优劣,毫无意义。
七、JavaScript 运行时的未来格局
7.1 三足鼎立的新时代
2026 年的 JavaScript 运行时格局:
| 运行时 | JS 引擎 | 核心语言 | 定位 |
|---|---|---|---|
| Node.js | V8 | C++ | 稳定性优先,生态最大 |
| Deno | V8 | Rust | 安全性优先,Web 标准 |
| Bun | JSC | Rust(原 Zig) | 性能优先,全家桶 |
7.2 Rust 正在成为运行时基础设施的默认选择
Bun 的 Rust 重写,加上 Deno 的 Rust 底层,以及 Turbopack、Rspack 等 Rust 工具链的成功,Rust 正在成为 JavaScript 基础设施的默认实现语言。
这不是偶然:
- JavaScript 运行时需要处理海量 I/O,对性能要求极高
- 运行时是基础设施,可靠性要求高,Rust 的内存安全保证价值巨大
- Rust 的 async 生态(tokio、async-std)已经足够成熟
- Rust 的跨平台支持(Linux、macOS、Windows、WASM)覆盖了所有场景
7.3 对开发者的实际影响
如果你是 JavaScript 开发者,这些变化意味着什么:
短期(2026-2027):
- Bun 的 Rust 版本会逐步稳定,性能优势进一步扩大
- Node.js 会继续渐进式引入 Rust 组件(如 undici HTTP 客户端)
- Deno 会继续深耕 Web 标准和安全性
中期(2027-2028):
- Rust 写的 JavaScript 工具链会成为主流(编译器、打包器、linter)
- JavaScript 运行时的性能天花板会被进一步推高
- AI 辅助的运行时开发会更加普遍
长期(2028+):
- JavaScript 运行时可能不再是"用 C++ 写的性能敏感组件 + 用 JS 写的业务逻辑"这种分层
- Rust 可能成为运行时基础设施的统一实现语言
- AI 可能参与更多运行时组件的开发
八、代码实战:用 Bun 构建高性能服务
8.1 Bun 的 HTTP 服务器
// server.ts - Bun 高性能 HTTP 服务器
const server = Bun.serve({
port: 3000,
maxRequestBodySize: 1024 * 1024 * 10, // 10MB
fetch(req) {
const url = new URL(req.url);
// 路由处理
switch (url.pathname) {
case "/":
return new Response("Hello from Bun!", {
headers: { "Content-Type": "text/plain" },
});
case "/api/users":
return Response.json([
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
]);
case "/api/health":
return Response.json({
status: "ok",
uptime: process.uptime(),
memory: process.memoryUsage(),
});
default:
return new Response("Not Found", { status: 404 });
}
},
});
console.log(`Bun server running at http://localhost:${server.port}`);
8.2 Bun 的文件操作
// file-ops.ts - Bun 的文件系统操作
import { readFileSync, writeFileSync } from "bun";
// 读取文件(异步)
async function readFile(path: string): Promise<string> {
const file = Bun.file(path);
const text = await file.text();
return text;
}
// 写入文件
async function writeFile(path: string, content: string): Promise<void> {
await Bun.write(path, content);
}
// 流式处理大文件
async function processLargeFile(path: string) {
const file = Bun.file(path);
const reader = file.stream().getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// 逐块处理
processChunk(value);
}
}
// SQLite 操作(Bun 内置)
import { Database } from "bun:sqlite";
const db = new Database("myapp.db");
db.run("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)");
const insert = db.prepare("INSERT INTO users (name) VALUES (?)");
insert.run("Alice");
insert.run("Bob");
const users = db.query("SELECT * FROM users").all();
console.log(users);
8.3 Bun 的测试
// test.ts - Bun 内置测试运行器
import { describe, it, expect } from "bun:test";
describe("HTTP Server", () => {
it("should return hello world", async () => {
const response = await fetch("http://localhost:3000/");
const text = await response.text();
expect(text).toBe("Hello from Bun!");
});
it("should return users list", async () => {
const response = await fetch("http://localhost:3000/api/users");
const data = await response.json();
expect(data).toHaveLength(2);
expect(data[0].name).toBe("Alice");
});
});
describe("File Operations", () => {
it("should read and write files", async () => {
const testPath = "/tmp/bun-test.txt";
await Bun.write(testPath, "Hello, Bun!");
const content = await Bun.file(testPath).text();
expect(content).toBe("Hello, Bun!");
});
});
运行测试:
$ bun test
✓ test.ts > HTTP Server > should return hello world
✓ test.ts > HTTP Server > should return users list
✓ test.ts > File Operations > should read and write files
3 pass, 0 fail
九、性能优化实战
9.1 避免不必要的内存分配
// ❌ 不好的写法:每次循环都创建新对象
function processItems(items: string[]) {
const results = [];
for (const item of items) {
const obj = { value: item.toUpperCase(), length: item.length };
results.push(obj);
}
return results;
}
// ✅ 好的写法:预分配数组大小
function processItemsOptimized(items: string[]) {
const results = new Array(items.length);
for (let i = 0; i < items.length; i++) {
results[i] = { value: items[i].toUpperCase(), length: items[i].length };
}
return results;
}
9.2 利用 Bun 的原生 API
// ❌ 用 Node.js 风格的 API
import { readFileSync } from "fs";
const data = readFileSync("large-file.txt", "utf-8");
// ✅ 用 Bun 的原生 API(更快)
const file = Bun.file("large-file.txt");
const data = await file.text();
// ✅ 流式处理大文件(内存友好)
const stream = Bun.file("large-file.txt").stream();
const reader = stream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// 处理每个 chunk
}
9.3 并发处理
// Bun 的并发处理
const urls = [
"https://api.example.com/users",
"https://api.example.com/posts",
"https://api.example.com/comments",
];
// 并发请求所有 URL
const responses = await Promise.all(
urls.map(url => fetch(url).then(r => r.json()))
);
// 使用 Bun 的 Task API 进行后台任务
const task = Bun.spawn(["node", "heavy-script.js"]);
const exitCode = await task.exited;
console.log(`Background task finished with exit code: ${exitCode}`);
十、总结与展望
10.1 Bun Rust 重写的三个核心启示
AI 工程化已经进入"机械替代"阶段:AI 不再只是辅助补全代码,而是可以承担大规模的机械性翻译工作。前提是有完善的测试套件和明确的翻译规则。
系统编程语言选型需要"场景思维":Rust 和 Zig 各有优势,脱离场景谈优劣毫无意义。Bun 选 Rust 是因为需要内存安全保证,Vercel 选 Zig 是因为需要快速迭代。
JavaScript 运行时正在进入"Rust 时代":从 Deno 到 Bun,再到 Turbopack 和 Rspack,Rust 正在成为 JavaScript 基础设施的默认实现语言。
10.2 开发者该怎么做?
如果你在用 Node.js:
- 不需要急于迁移到 Bun,Node.js 的生态依然最成熟
- 关注 Bun 的 Rust 版本稳定性,等它稳定后再考虑迁移
- 可以在新项目中尝试 Bun,特别是对性能敏感的场景
如果你在用 Bun:
- 升级到最新的 canary 版本(
bun upgrade --canary)体验 Rust 版本 - 关注官方的迁移指南,确保你的代码在新版本上正常运行
- 利用 Bun 的内置工具(包管理、测试运行器)简化开发流程
如果你在做基础设施:
- 考虑用 Rust 重写性能关键组件
- 建立完善的测试套件,为未来的 AI 辅助迁移做准备
- 关注 unsafe 代码的安全审计
10.3 未来展望
Bun 的 Rust 重写只是开始。我们可以预见:
- 更多运行时组件会用 Rust 重写:V8 的部分组件、Node.js 的 I/O 层、Deno 的核心引擎
- AI 会参与更多基础设施开发:不仅是代码翻译,还包括代码审查、性能优化、bug 修复
- JavaScript 运行时的性能天花板会被持续推高:Rust 的性能优势会让 JS 运行时接近原生性能
Jarred Sumner 那句"未来开源可能禁止人类提交代码"的预言,虽然听起来极端,但它指向了一个真实的趋势:AI 正在从"辅助工具"变成"工程伙伴"。Bun 的 Rust 重写,就是这个趋势的第一个大规模实践案例。
参考资源:
- Bun GitHub: https://github.com/oven-sh/bun
- Bun Rust 重写 PR: https://github.com/oven-sh/bun/pull/30412
- ZeroNative: https://github.com/vercel-labs/zero-native
- Jarred Sumner 推特: https://x.com/jarredsumner