Node.js Can Now Be Packaged as an EXE—Evan You Shows It Starts Faster Than Bun

Node.js now supports Single Executable Applications (SEA) with ESM entry points, allowing developers to bundle code and the runtime into a single binary, and benchmarks by Evan You demonstrate that the resulting executable launches faster than Bun's compiled mode.

Node.js Tech Stack
Node.js Tech Stack
Node.js Tech Stack
Node.js Can Now Be Packaged as an EXE—Evan You Shows It Starts Faster Than Bun

What Is Node.js SEA?

SEA stands for Single Executable Applications . Traditionally, a Node.js program requires the runtime to be installed, then npm install and node app.js to run. SEA bundles your script together with the V8 engine into a single binary that runs by double‑clicking, without any environment dependencies.

Distribute CLI tools : team members can run a scaffold without installing Node.

Deliver client applications : ship a single clean file to customers.

CI/CD pipelines : reduce build‑environment dependency management.

Edge/embedded : deploy Node apps on resource‑constrained devices.

Unlike Go or Rust, Node.js must bundle the entire V8 engine and your scripts, which makes the implementation technically distinct.

From "Usable" to "Polished": Three Years of Development

2023‑early (v19.7.0): SEA landed but required a cumbersome manual process using an external tool postject to inject a blob into a Node binary, with many low‑level steps and poor documentation.

2023‑2025 (v20 → v24): Iterations added JSON config, asset bundling, V8 code cache, etc., but still relied on postject and only supported CommonJS, leaving ESM projects unable to use SEA.

2026‑01‑26 (v25.5.0): Joyee Cheung moved the injection logic into the Node core, integrating the LIEF library to handle ELF, PE, and Mach‑O formats. SEA can now be built with a single command: node --build-sea sea-config.json Later on 2026‑02‑18, PR #61813 added ESM entry‑point support, completing the feature set.

Why ESM Support Matters

By 2026 most new projects use ESM ( import/export) instead of CommonJS ( require). Previously SEA only accepted CJS entry points, forcing developers to downgrade or abandon SEA. PR #61813 introduced a "mainFormat": "module" field in the SEA config, enabling ESM parsing and features such as import, dynamic import(), top‑level await, and meta‑information ( import.meta.url, import.meta.filename, import.meta.dirname).

Current limitations: ESM mode does not yet support V8 code cache ( useCodeCache) or startup snapshots ( useSnapshot), and import.meta.resolve awaits VFS support.

tsdown --exe: One Command Does It All

With the --build-sea flag, the workflow is simplified, but TypeScript developers still need to compile to JavaScript before building the executable. The upcoming tsdown version (based on Rolldown) will embed a --exe flag to perform "TS compile + bundle + SEA generation" in a single step.

Evan You benchmarked the result: a Node.js SEA built with Rolldown starts faster than bun --compile. However, Bun 1.3.9 later introduced bytecode optimizations that made its startup about 25 % faster than Node.js SEA with code cache.

Hands‑On: Build a Node.js SEA in Five Minutes

Step 1 – Create hello.js:

// hello.js
console.log(`Hello, ${process.argv[2] || 'World'}!`);

Step 2 – Create sea-config.json:

{
  "main": "hello.js",
  "output": "hello"
}

Step 3 – Generate the executable: node --build-sea sea-config.json Step 4 – Run it:

./hello Node.js
# Output: Hello, Node.js!

On macOS you may need to sign the binary: codesign --sign - hello For ESM projects, adjust the config to include:

{
  "main": "app.mjs",
  "output": "my-app",
  "mainFormat": "module"
}

With TypeScript + tsdown, the command simplifies to:

tsdown --exe

The Contributor Behind SEA: Joyee Cheung

Joyee Cheung, a core Node.js contributor, drove the migration of the SEA build process into the core, integrated the LIEF library for cross‑platform binaries, and implemented ESM entry support (PR #61813). She recounts that after early contributors left, development stalled until she revived the project during a vacation, read LIEF documentation, and submitted the pivotal PR.

This story illustrates how critical features in large open‑source projects often rely on the persistence of a few dedicated engineers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendNode.jsPackagingESMExecutableSEAtsdown
Node.js Tech Stack
Written by

Node.js Tech Stack

Focused on sharing AI, programming, and overseas expansion

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.