1 个不稳定版本
使用旧 Rust 2015
0.2.1 | 2018 年 11 月 22 日 |
---|
#4 in #es6
365KB
7K SLoC
关于 JavaScript Binary AST 的介绍
随着网站变得越来越复杂,JavaScript 源代码的数量也在不断增加。虽然依赖大型 JavaScript 代码库不会阻止网站工作,但它会导致网站启动缓慢——往往非常 慢,难以接受。这是由于两个瓶颈:解析和编译 JavaScript 字节码。不幸的是,浏览器在这两项操作上的效率已经接近极限。
我们(Mozilla、Bloomberg、Facebook、CloudFlare)目前正在开发一种针对 JavaScript 的特定领域编码,称为“BinAST”(即“JavaScript Binary AST”)。JavaScript Binary AST 的设计目的是打破这个瓶颈。当前的高级原型已经显示出 JS 在所有最常见的框架中解析速度提高了 30%-50%(见链接),只需更改格式,我们相信我们可以进一步提高这个改进。这种编码可以作为 Web 开发工具链的一部分来构建,或者由代理或 CDN 注入,从而在不修改原始网站的情况下自动提高最终用户的性能。
这种编码目前正在 JavaScript TC39 标准化过程中 [3]。它可以与现有的压缩技术(gzip、brotli 等)一起使用
测试它
- 安装依赖(您需要
npm
,rustup
)
npm install
rustup install nightly
rustup default nightly
- 拉取代码。
git clone https://github.com/binast/binjs-ref
- 压缩/解压缩。
cargo run --bin binjs_encode -- --help
cargo run --bin binjs_decode -- --help
注意 JS 解析器可能会在非常大的 JS 源文件上失败。如果是这样,您需要设置环境变量 NODE_MAX_OLD_SPACE_SIZE=xxxx
。这将指示基于 Node 的解析器分配更多的内存。默认值是 2048(Mb)。这相当于向 Node 进程传递 --max_old_space_size
。
- 转储树结构。
cargo run --bin binjs_dump -- --help
注意 binjs_dump
仅支持 multipart
格式。
与 JavaScript 源代码的兼容性
保留
- 良好形成程序的语义;
- 变量和函数名称。
不保留
- 语法错误的实际语义;
- 源代码位置;
- 格式化(包括空白符和分号);
- 注释(包括源映射)。
预期的好处
二进制 AST 格式设计得比 JS 源代码解析得更快,这得益于无需回溯的语法,不需要多次 intern 的字符串等。
二进制AST格式设计得非常巧妙,使得虚拟机可以在接收到文件的前几个字节后立即开始解析文件(流式解析),并在之后很快开始编译为字节码(流式字节码编译)。
此外,对JavaScript源代码的解析指定了特定的编码,这意味着在解析之前(或者在最佳情况下,在解析的同时)需要对这些编码进行转码,这会减慢解析速度。由于BinAST是一种二进制格式,因此不需要任何形式的转码。
最后,大多数现代JavaScript虚拟机支持一种懒解析的形式,这种解析方式在几乎不进行内存分配的情况下执行更快的解析。BinAST格式设计得允许解析器通过单个操作跳过(函数),从而在需要时使懒解析更高效。
规范
lib.rs
:
ES6 AST的强类型实现。
依赖项
~12MB
~361K SLoC