传统 JavaScript 运行时如 Node.js 或浏览器引擎,通常打包庞大的解释器或 JIT 编译器,导致独立可执行文件体积巨大(往往数十 MB),启动时间长,且高度依赖特定 VM 环境。这限制了 JS 在嵌入式设备、CLI 工具或边缘计算中的应用。Porffor 和 QuickJS 等项目通过原生编译(AOT)技术,将 JS 字节码解释器直接转化为 VM 独立的 standalone 可执行文件,实现 “运行时自由”,显著缩小体积并提升性能。
Porffor 是一个实验性 AOT 编译器,完全用 JS 编写,支持将 JS/TS 直接编译为 WebAssembly 或原生二进制。它不捆绑运行时,而是真正编译 JS 代码,通过 JS → Wasm → C → native 的链路生成文件。例如,传统 JS-to-native 方案体积约 90MB,而 Porffor 输出小于 100KB,缩小 1000 倍。该项目强调静态分析优化,支持 TypeScript 无需转译。
安装 Porffor 简单:npm install -g porffor@latest。基本使用:
- REPL 模式:
porf - 运行 JS:
porf script.js - 编译 Wasm:
porf wasm script.js out.wasm - 原生编译:
porf native script.js out.exe
关键参数包括:
--compiler=clang|gcc|zig:选择 C 编译器,默认 clang。--cO=Ofast|O3|O2|O1|O0:优化级别,默认 Ofast(最高性能)。--valtype=i32|i64|f64:数值类型,默认 f64。--opt-types:启用类型优化提示。
示例脚本 fib.js 计算斐波那契数:
function fib(n) { return n <= 1 ? n : fib(n-1) + fib(n-2); }
console.log(fib(30));
编译:porf native fib.js fib --cO=Ofast --compiler=clang。生成 exe 启动瞬间执行,无 Node 依赖,适用于 CLI 工具。
QuickJS 是另一个轻量级 JS 引擎,仅几百 KB,支持 ES2023 规范,包括模块、异步生成器。通过 qjsc 工具编译 JS 为独立字节码可执行文件:
./qjsc -o hello examples/hello.js
./hello # 输出 Hello World
体积小(hello world 仅 367 KiB),启动 <300μs,垃圾回收用引用计数。参数:
-m:模块模式。-fno-eval:禁用动态 eval。--std:启用 std/os 模块(文件 I/O)。
落地清单:
- 环境准备:Node.js(Porffor)/C 编译器(QuickJS),目标平台 Clang/GCC。
- 代码规范:避免 eval/new Function;用类型注解
/** @type {number} */优化 Porffor;静态函数优先。 - 编译流程:
步骤 命令 输出体积阈值 性能阈值 Wasm porf wasm script.js <10KB 启动 < 1ms Native porf native --cO=Ofast <100KB 接近 C QuickJS qjsc script.js out <500KB 启动 < 300μs - 监控点:文件大小(strip 默认启用);冷启动时间(benchmark);Test262 兼容率(Porffor 持续测试)。
- 回滚策略:若不支持动态 JS,回退 Node;体积超阈值,禁用 BigInt 等扩展(QuickJS
-fno-bigint)。
风险与限制:
- Porffor 预 alpha,不支持异步 / 跨域变量,实验性强。
- QuickJS 无尾调用优化,数学扩展可选。
- 两者均静态,无法动态加载代码。
实际场景:CLI 工具(如 JSON 处理器),体积从 Node 90MB 缩至 <1MB;边缘计算,Wasm 沙箱安全执行。Porffor 适用于高性能嵌入式,QuickJS 适合脚本嵌入。
这些技术解放 JS 运行时,实现真正独立部署,推动 JS 向系统级语言演进。
资料来源:
- Porffor 官网:https://porffor.dev/
- QuickJS 官网:https://bellard.org/quickjs/
- HN 讨论:https://news.ycombinator.com/(相关 JS 编译帖子)