我把我的第一个项目过度工程化:用 Bun 桥接 TypeScript 与 Zig!🚀
Source: Dev.to
你好,你好!又是我 Owen!
我已经有一段时间没有活动了,觉得也许该再发点东西了。有些人说编码项目应该从待办清单、REST API、生成器等开始。相反,我直接跳进深水区:我想快速构建一些东西,学习内存管理,并弄清楚不同语言之间是如何通信的。
于是,我创建了 Dunena——一个高性能、混合架构的 monorepo。它利用 Bun 和 TypeScript 处理 Web 层,并通过外部函数接口(FFI)将繁重的 CPU 任务委托给 Zig。我还把它部署在 Kubernetes 上(仍在学习 Docker 和 K8s)。
🔗 Dunena Repository on GitHub
🔗 Documentation
什么是 Dunena?
在核心层面,Dunena 是一个后端平台,旨在快速高效地处理请求。它包括路由、WebSockets、发布/订阅服务以及缓存层。
真正的魔法在于底层:我想要 TypeScript 的快速开发速度,但又不希望 Node/Bun 因压缩、布隆过滤器或复杂的统计计算等重计算而变得迟缓。
技术栈
- 运行时 & 单仓库管理器: Bun 🥟
- 主要语言: TypeScript (strict mode)
- 高性能核心: Zig ⚡
- 数据库: SQLite 🗄️
- 部署: Docker & Kubernetes 🐳
架构
项目中最酷(也是最吓人)的部分是 FFI 桥接。下面展示了请求如何从 TypeScript 传递到几乎裸金属的 Zig 执行。
Zig 端
// zig/src/exports.zig
const std = @import("std");
// Export a function so Bun can read it via the C ABI
export fn compute_heavy_stats(input_val: i32) i32 {
// Imagine some incredibly complex, CPU‑blocking math here
var result = input_val * 42;
return result;
}TypeScript 端
// packages/platform/src/bridge/ffi.ts
import { dlopen, FFIType, suffix } from "bun:ffi";
// Load the compiled Zig library
const path = `../../zig/zig-out/lib/libdunena_core.${suffix}`;
const { symbols } = dlopen(path, {
compute_heavy_stats: {
args: [FFIType.i32],
returns: FFIType.i32,
},
});
// Now I can call Zig directly from TypeScript!
export function runStats(input: number): number {
return symbols.compute_heavy_stats(input);
}当客户端访问 Bun 服务器(apps/server/src/index.ts)时,平台负责 API 路由,将繁重的计算交给 Zig 处理,并立即返回结果。
“AI”大象在房间里
我使用 AI 编码代理(Claude、Gemini)来加速样板代码、搭建 monorepo 结构,并搭建初始文件架构。AI 帮我快速推进,但我仍然必须进行残酷的、抓狂的调试和修复:
- 如果 AI 在 Zig 中更改了数据类型,却忘记在 TypeScript 中更新相应的 FFI 定义,服务器会因内存访问违规而崩溃。
- 管理指针、防止内存泄漏,以及让 Kubernetes 与附加的 SQLite 卷一起工作,都需要细致的人为监督。
这次经历让我明白,尤其在处理底层系统时,不能盲目信任生成的代码。
最大的挑战
1. 跨越虚空的内存管理
在 TypeScript 与 Zig 之间传递数据没有安全网。Bun 的垃圾回收器对 Zig 的内存管理一无所知,所以我必须学习 Zig 中的手动分配和 defer 语句。
2. Kubernetes 中的 SQLite
通过持久卷声明(Persistent Volume Claims)在 K8s Pod 上部署 SQLite(基于文件的数据库)对单个 Pod 可行,但水平扩展时可能会导致数据库锁定问题。
接下来是什么?
项目远未“完成”。我目前独自维护,但欢迎贡献。未来的想法包括:
- 使用更安全的抽象来改进 FFI 层。
- 探索替代存储方案,以实现更好的水平扩展。
- 添加更多高性能的 Zig 模块(例如图像处理、密码学)。
让我们联系!
我很期待社区的任何反馈、代码审查或建议。
你有没有遇到过这样混合语言或与 FFI 边界搏斗的情况?在评论中告诉我吧! 👇