乐于分享
好东西不私藏

Bun 源码解析:用 Zig 重写 JavaScript 运行时的极速之路

Bun 源码解析:用 Zig 重写 JavaScript 运行时的极速之路

引言

Bun 是一个用 Zig 语言编写的 JavaScript/TypeScript 运行时,集运行时、打包器、测试框架和包管理器于一体。它的目标很直接:比 Node.js 快,比 npm 快,比 webpack 快——而且是同一个工具。

项目背景

Bun 由 Jarred Sumner 创建,使用 Zig 语言编写,底层使用 JavaScriptCore(Safari 的 JS 引擎)而非 V8。选择 Zig 的原因:手动内存管理带来极致性能,与 C 的无缝互操作,编译时计算减少运行时开销。

核心源码解析

1. JavaScriptCore 集成

与 Node.js 使用 V8 不同,Bun 选择了 JavaScriptCore:

// Bun 的 JS 引擎绑定(简化)
const JSC = @import("javascript_core");

pub fn evaluate(global: *JSC.JSGlobalObject, source: []const u8) !JSC.JSValue {
    const result = global.evaluateScript(source);
    return result;
}

JSC 的启动速度比 V8 快,内存占用更低,这是 Bun 冷启动快的关键因素之一。

2. 原生打包器

Bun 内置了打包器,直接在 Zig 层面实现模块解析和打包:

pub const Bundler = struct {
    resolver: Resolver,
    parser: Parser,
    linker: Linker,

    pub fn bundle(self: *Bundler, entry: []const u8) !BundleResult {
        const resolved = try self.resolver.resolve(entry);
        const ast = try self.parser.parse(resolved);
        return try self.linker.link(ast);
    }
};

因为打包器和运行时共享同一个解析器,避免了重复解析的开销。

3. 包管理器

Bun 的包管理器通过并行下载和硬链接实现极速安装:

pub const PackageManager = struct {
    // 全局缓存,所有项目共享
    global_cache: GlobalCache,

    pub fn install(self: *PackageManager) !void {
        // 1. 解析依赖树
        // 2. 并行下载所有包
        // 3. 使用硬链接而非复制,节省磁盘空间
    }
};

硬链接策略意味着同一个包在磁盘上只存储一份,所有项目共享。

关键设计模式

1. 全栈集成:运行时、打包器、包管理器共享底层基础设施,消除重复工作。 2. 系统级语言优势:Zig 的手动内存管理和编译时优化带来极致性能。 3. 引擎选择差异化:JSC 替代 V8,在启动速度和内存效率上取得优势。

总结

Bun 的设计哲学是”一个工具解决所有问题”。通过 Zig 语言的性能优势和全栈集成的架构设计,它在 JavaScript 工具链的每个环节都实现了显著的性能提升。