Skip to content

Repository files navigation

Banderole

Create cross-platform single-executables for Node.js projects. Windows is not supported.

Banderole bundles your Node.js app, all dependencies, and a portable Node binary into a single native executable. On first launch, it unpacks to a cache directory for fast subsequent executions.

Unlike Node.js SEA or pkg, banderole handles complex projects with dynamic imports and non-JavaScript files without requiring patches — it ships a stock Node binary and your real dependency tree rather than a patched runtime and a virtual filesystem.

Performance

Measured on linux-x64, Node 22.17.1, against @yao-pkg/pkg 6.22.0 building the same app. Startup is the median of 60 interleaved runs (targets rotate every round, so machine drift affects both equally).

trivial app app with deps
(express, lodash, chalk, dayjs)
banderole pkg banderole pkg
Executable size 33,416,408 B 74,306,703 B 35,366,424 B 77,346,956 B
Startup (median) 16.1 ms 25.7 ms 53.1 ms 78.8 ms
Resident processes 1 1 1 1
Resident memory (RSS) 43.8 MiB 49.4 MiB 66.4 MiB 76.2 MiB

pkg's size floor is the uncompressed Node binary it embeds, which its --compress option does not touch. banderole compresses the Node binary with zstd and ships only the executable itself, so a bundle is roughly half the size.

The trade-off is the first launch, which unpacks the payload into the cache directory: 117 ms versus pkg's 30 ms for the trivial app. Every launch after that takes the warm path above.

Scaling with project size

First-launch extraction grows with the dependency tree; steady-state launch does not, because it is one file read followed by exec.

node_modules files bundle time first launch every later launch
0 16 s 159 ms 19.4 ms
14 MB 5,500 18 s 224 ms 22.4 ms
68 MB (real npm tree) 9,725 19 s 316 ms 71.2 ms
143 MB 27,500 20 s 348 ms 23.3 ms
763 MB 110,000 25 s 862 ms 22.9 ms

A 763 MB dependency tree still unpacks in under a second, and warm launch is flat across the whole range. (The 68 MB row is a real npm install; its higher warm figure is Node resolving express/lodash/dayjs at runtime, not launcher overhead. The other rows are generated trees, which compress better than real ones.)

Requirements

Banderole requires a Rust toolchain (cargo, rustc, rustup) and a working C linkercc/gcc/clang on Unix, MSVC on Windows — because it compiles a small launcher for each bundle.

Installation

cargo install banderole

Usage

# Bundle a project using the project name
banderole bundle /path/to/project

# Bundle with custom output path
banderole bundle /path/to/project --output /path/to/output/executable

# Bundle with custom name
banderole bundle /path/to/project --name my-app

# Bundle with both custom output and name
banderole bundle /path/to/project --output /path/to/my-app --name my-app

Feature List

  • Support Linux, MacOS, and Windows for both x64 and arm64 architectures.
  • Support custom node.js version based on project's .nvmrc and .node-version
  • Support TypeScript projects with automatic detection of compiled output directories
  • Support workspaces (only pnpm workspaces tested)
  • Only the executable has permissions to read and execute bundled files

License

MIT

About

Create portable single-executables for Node.js apps

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages