You’re not imagining things: Some JavaScript web apps are quite slow, owing to egregiously high startup, parsing, and data transfer overhead. According to HTTPArchive, which periodically crawls popular websites and records information about fetched resources, the average page requires 350KB of JavaScript (10% of pages exceed 1MB). And once these pages are transferred, JavaScript engines must check for syntax errors and compile them (assuming they aren’t cached). That takes around 100 milliseconds for a 1MB file on a high-end mobile device, or over a second on an average phone.

A solution potentially lies in BinaryAST, a new “over-the-wire” JavaScript format proposed by Mozilla (with support from Facebook, Bloomberg, and others) that aims to speed up parsing while retaining JavaScript’s original semantics. How? By using an efficient binary representation for code and data structures and by storing and providing guiding information to the parser ahead of time. While the format remains somewhat in flux, the first version of the client was released under a flag in Firefox Nightly several months ago, and content delivery service Cloudflare recently became one of the first to provide the necessary cloud-hosted JavaScript engine in its Cloudflare Workers execution environment.

BinaryAST speed tests

Above: JavaScript speed tests.

Image Credit: BinaryAST

So just how much fasterĀ is BinaryAST? In tests, Mozilla measured the load times of 3.3MB Javascript apps at 476 milliseconds on desktop (BinaryAST) versus 677 milliseconds (JavaScript), and 2,794 milliseconds on smartphones like the HTC One M8 versus 3,579 milliseconds. Moreover, Mozilla has recorded parsing time improvements of between 90-97%.


Traditionally, browsers parse JavaScript into intermediate representations called abstract syntax trees (AST) that describe the steps to run the code, which are then compiled into machine code or sent to a just-in-time (JIT) compiler to be executed client-side. BinaryAST makes it possible only to parse code necessary for startup, as opposed to entire files, thereby reducing the overall amount of work the browser parser must perform.

Here’s how:

  • JavaScript relies on hoisting for declarations (i.e., variables, functions, and classes), which allows developers to declare items after the point they’re syntactically used. BinaryAST stores all scope information by making it available upfront before the expressions.
  • Modern browser engines use lazy parsing, wherein some functions are preparsed, skipped, or delayed rather than fully parsed via an abstract syntax tree. Normally, this requires handcrafted heuristics for each function body, but with BinaryAST, the browser parser can lean on JavaScript that’s been analyzed and verified and so skip function bodies entirely. This makes lazy parsing effectively “free.”
  • A class of errors called “early errors” is run against the source to check for mistakes like reserved words in invalid contexts, strict mode violations, and variable name clashes before running the actual parser. BinaryAST can spot these errors ahead of time, before runtime.
  • Parsing low-level types, like numbers from text, requires extra computation, and some functions are ambiguous until fully parsed (either through backtracking or with intermediate node types). BinaryAST exposes the node type upfront prior to parsing.

The current BinaryAST prototype implemented by Cloudflare and Mozilla runs JavaScript sources through a parser to generate the AST, which the encoder (written in Rust and fully native) annotates before writing out the result in one of several supported formats. Within Cloudflare Workers, the native Rust encoder is compiled to WebAssemly (a binary instruction format for a stack-based virtual machine), and Node.js instances to run the JavaScript parser code are spun up in the same process as required.

Overhead data transfer, CPU overhead, and memory usage are reduced by retrieving required bits directly from the JavaScript AST, Mozilla says, such that all native typed AST structures can be deserialized using a deserializer directly from the Node.js process in a streaming manner. Additionally, this deserializer can use its knowledge of Rust types and cache all the serialized property names as JavaScript value handles just once and reuse them for further property accesses, again boosting performance.

Enabling Binary AST in Firefox

Above: Enabling Binary AST in Firefox.

Looking to get started with BinaryAST? You’re in luck — the BinaryAST Worker can be installed on any Cloudflare website. After it’s configured, downloading the Firefox Nightly, heading to the about:config page, and enabling unrestricted BinaryAST will get things up and running.