
BlueJS is a groundbreaking new compiler that turns JavaScript into tiny native binaries without bundling V8. We explore how it works, what it's good for, and where it fits in the future of JavaScript deployment.
๐ก TL;DR: BlueJS is a new JavaScript-to-native compiler that produces standalone executables weighing just 1.2MB โ without shipping the V8 engine. This could be a game-changer for CLI tools, serverless, and embedded use cases.
For most of JavaScript's history, running JS outside a browser has meant shipping a JavaScript engine โ typically V8 โ alongside your code. Node.js does this. Deno does this. Bun brings its own engine (JavaScriptCore). Even tools like pkg and nexe that produce "standalone" Node.js binaries still bundle the entire Node runtime, resulting in executables often exceeding 40โ80MB.
Enter BlueJS: a compiler that takes your JavaScript source and emits a genuine native binary. Not "native with a hidden runtime tucked inside." A real, lean, machine-code executable at just 1.2MB.
This post explores how BlueJS works, where it fits into the ecosystem, and what it means for the future of JavaScript deployment.
Tools like pkg, nexe, or Node.js's experimental Single Executable Applications (SEA) all solve the distribution problem by bundling the Node.js runtime with your app. This works but has real costs:
| Tool | Typical Binary Size | V8 Included? |
|---|---|---|
| pkg | ~40โ80 MB | โ Yes |
| nexe | ~35โ70 MB | โ Yes |
| Node SEA | ~30โ60 MB | โ Yes |
| Bun compile | ~10โ15 MB | โ Yes (JSC) |
| BlueJS | ~1.2 MB | โ No |
In serverless environments like AWS Lambda or Cloudflare Workers, binary size directly impacts cold start time. A 60MB binary that needs to initialize V8 is orders of magnitude slower to boot than a 1.2MB native binary that starts executing machine instructions immediately.
BlueJS uses Ahead-of-Time (AOT) compilation to convert JavaScript into native machine code. Here's a simplified view of the pipeline:
JavaScript Source (.js)
โ
โผ
Parsing & AST Generation
โ
โผ
Type Inference & Analysis
โ
โผ
IR (Intermediate Representation)
โ
โผ
Native Code Generation (LLVM)
โ
โผ
Native Binary (.exe / ELF / Mach-O)
1. Static Type Inference JavaScript is dynamically typed, but BlueJS analyzes your code statically to infer types where possible. Inferred types allow the compiler to emit more efficient machine code โ skipping dynamic dispatch and type checks at runtime.
2. Escape Analysis & Stack Allocation BlueJS determines which objects never "escape" their local scope and allocates them on the stack instead of the heap, drastically reducing garbage collection pressure.
3. LLVM Backend The compiler targets LLVM IR, which means it benefits from decades of optimization research built into LLVM โ including loop unrolling, inlining, vectorization, and dead code elimination.
4. Minimal Runtime Rather than a full JS engine, BlueJS ships with a tiny runtime stub that provides only what's strictly needed: basic memory management, a minimal standard library, and OS interfacing. This is what keeps the binary at 1.2MB.
Installation is straightforward:
npm install -g bluejs-compiler
Compiling your first script:
bluejs compile app.js --output app
./app
For cross-compilation to different targets:
# Compile for Linux x64
bluejs compile app.js --target linux-x64 --output app-linux
# Compile for macOS ARM64
bluejs compile app.js --target darwin-arm64 --output app-macos
# Compile for Windows x64
bluejs compile app.js --target win32-x64 --output app.exe
Distributing a CLI tool as a native binary means zero install friction. No npm install, no Node.js prerequisite, no PATH issues. Users just download and run:
# Before BlueJS: user needs Node.js installed
npm install -g my-awesome-cli
# After BlueJS: just a binary download
curl -L https://releases.myapp.com/my-awesome-cli-linux && chmod +x my-awesome-cli-linux
Tiny binaries mean dramatically faster cold starts. A BlueJS-compiled Lambda function could start in under 5ms, compared to 200โ500ms for a Node.js Lambda that needs to initialize the runtime and parse your bundle.
Running JavaScript logic on resource-constrained hardware has always been challenging. BlueJS opens the door to deploying JS-based business logic on devices with limited RAM and storage where V8 is simply not an option.
Shipping a 1.2MB binary to edge nodes worldwide is trivially fast. This makes BlueJS a compelling option for building edge-native JavaScript services.
BlueJS is powerful, but it's not a silver bullet. Here are the important limitations to understand before adopting it:
JavaScript's most dynamic features are difficult or impossible to AOT-compile:
// These patterns may not work in BlueJS:
eval("console.log('hello')"); // โ eval
new Function("return 42")(); // โ Function constructor
const mod = require(someVariable); // โ Dynamic require
const prop = obj[computedKey]; // โ ๏ธ Limited support
Not all npm packages will work. Packages that rely on Node.js-specific APIs (fs, net, child_process, etc.) will need compatibility shims or may be unsupported. Pure utility libraries (lodash, zod, date-fns) are far more likely to work out of the box.
V8's JIT compiler is extraordinarily good at optimizing hot paths at runtime based on actual usage patterns. BlueJS's AOT compilation produces good static code, but may not match V8's peak throughput for compute-intensive workloads.
| Feature | Node.js + pkg | Bun compile | BlueJS |
|---|---|---|---|
| Binary size | 40โ80MB | 10โ15MB | 1.2MB |
| npm compatibility | โ Full | โ High | โ ๏ธ Partial |
| Dynamic JS support | โ Full | โ Full | โ ๏ธ Limited |
| Cold start speed | Slow | Fast | Very Fast |
| Maturity | Stable | Stable | Experimental |
BlueJS represents a fascinating new direction for JavaScript. We're increasingly seeing the language break free from its runtime monoculture (V8 everywhere). Between Bun's JavaScriptCore, Deno's V8 sandbox, WasmGC-based JS engines, and now AOT compilers like BlueJS, the ecosystem is diversifying in exciting ways.
๐ The future of JavaScript isn't one runtime โ it's the right runtime for each deployment target.