编程 Bun 深度拆解:一个 JavaScript 运行时如何让 Claude Code 在 9 天内用 Rust 重写自己——从 Zig 到 Rust 的百万行 AI 工程实践全解析

2026-08-03 09:14:15 +0800 CST views 5

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 的策略是:

  1. 保持架构不变:不改变 Bun 的架构设计和数据结构
  2. AI 做机械翻译:让 Claude Code 将 Zig 代码逐文件翻译为 Rust
  3. 人类做架构决策:团队负责审查 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 版本的优势:

  • 所有权系统确保回调函数不会在执行后被意外使用
  • 借用检查器防止事件循环在遍历时被修改
  • VecDequeBinaryHeap 的内存管理由 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 倍以上,这得益于:

  1. 使用系统原生的 I/O 多路复用(io_uring/kqueue)
  2. 自研的 HTTP 解析器(不依赖 llhttp)
  3. 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 做机械翻译,人类做架构决策

这种模式的前提是:

  1. 代码有明确的翻译规则(Zig → Rust 的语法映射)
  2. 有完善的测试套件验证正确性(99.8% 通过率)
  3. 架构保持不变,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 checkerZig 的简洁
高性能运行时✅ 内存安全保障❌ 需要手动管理
桌面/移动应用壳❌ 开发节奏拖慢✅ 快速迭代
大型开源项目✅ 长期可维护性❌ 维护成本高
小型工具❌ 过度工程化✅ 轻量简洁

这是工程决策最真实的样子:脱离场景谈语言优劣,毫无意义。

七、JavaScript 运行时的未来格局

7.1 三足鼎立的新时代

2026 年的 JavaScript 运行时格局:

运行时JS 引擎核心语言定位
Node.jsV8C++稳定性优先,生态最大
DenoV8Rust安全性优先,Web 标准
BunJSCRust(原 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 重写的三个核心启示

  1. AI 工程化已经进入"机械替代"阶段:AI 不再只是辅助补全代码,而是可以承担大规模的机械性翻译工作。前提是有完善的测试套件和明确的翻译规则。

  2. 系统编程语言选型需要"场景思维":Rust 和 Zig 各有优势,脱离场景谈优劣毫无意义。Bun 选 Rust 是因为需要内存安全保证,Vercel 选 Zig 是因为需要快速迭代。

  3. 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 重写,就是这个趋势的第一个大规模实践案例。


参考资源

推荐文章

维护网站维护费一年多少钱?
2024-11-19 08:05:52 +0800 CST
PHP 8.4 中的新数组函数
2024-11-19 08:33:52 +0800 CST
前端代码规范 - Commit 提交规范
2024-11-18 10:18:08 +0800 CST
Python设计模式之工厂模式详解
2024-11-19 09:36:23 +0800 CST
10个极其有用的前端库
2024-11-19 09:41:20 +0800 CST
程序员茄子在线接单