你以为 JS 可执行文件只能靠 V8?今天 Deno 用 QuickJS 把这件事彻底变了

你以为 JS 可执行文件只能靠 V8?今天 DenoQuickJS 把这件事彻底变了。

你第一次跑 deno compile app.ts 大概是这个反应:一个几十行的 hello world,打出来的二进制 64MB。

这个数字不是 Deno 加的,是 V8。V8 是 Google 的 JavaScript 引擎,为了跑出极致性能,把 JIT 编译器、垃圾回收、字节码缓存全塞进去了。性能是上去了,体积也跟着上去了。对于真正只需要读个文件、调用一个 API、打印结果的 CLI 工具来说,这 64MB 里有 60MB 是你根本用不上的。

Deno 2.9.5 今天给出了一个你没想过的答案:换引擎。

deno compile --engine quickjs main.ts

QuickJS 是 Fabrice Bellard(FFmpeg、QEMU 的同一个作者)写的 JavaScript 引擎,定位从来就不是跑分第一。它追求的是更小、更快启动、更容易嵌入。ES2023 全支持,但没有 JIT,字节码直接跑。

同样的代码:

引擎 二进制体积 冷启动速度
V8(默认) 64 MB 基准
QuickJS 35 MB 快约 25%

45% 的体积缩减,冷启动快 25%,同样的 CLI、同样的 TypeScript 代码。这就是 --engine quickjs 做的事。

不过这不是非此即彼的选择。QuickJS 后端是实验性质的,上生产之前有几件事要想清楚:

安全更新不上线。V8 有 Google 安全团队持续打补丁,QuickJS 没有这个待遇。如果你编译的是一个跑在公网、处理不受信任输入的服务,别用 QuickJS。

没有 JIT,计算密集型代码慢。QuickJS 是纯解释器,跑一个 MD5 摘要或者图片处理这种 CPU 密集任务,性能差距会很明显。但如果你的 CLI 工具瓶颈在 IO 不在 CPU,这个差异你感知不到。

生态兼容需要测试。QuickJS 后端是实验性质,行为差异虽然罕见但有可能。在你的目标平台上实际跑一遍再发货。

什么场景适合 QuickJS?做 LLM 钩子脚本、git hook、CI step、edge function 这些场景,二进制大小和冷启动速度才是主要矛盾。3MB 的脚本拖着 35MB 的运行时,和 3MB 的脚本只拖 1MB 的运行时,在 Serverless 按调用计费的场景里差距是真实的。

下一步:如果你有个跑了很久的 Deno CLI 工具,deno compile --engine quickjs --target x86_64-unknown-linux-gnu main.ts 编译一版看看体积变化。3 分钟的事,说不定你那个原来 64MB 的部署包就变成 35MB 了。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 50 阅读