Skip to main content

Distributing executable binaries in npm package

·

Let’s say you need to distribute binary in npm. I’m not talking about node extensions (node-gyp, napi, etc.). I’m talking about standalone executables, like CLI applications.

We have options. How to distribute binary:

  1. host executables on some server, for example, GitHub releases, and download appropriate (e.g. for given OS and architecture) binary on installation
  2. put all executables (for all OSs and architectures) in one npm package
  3. create sub-packages with binary for each OS and architecture and one “root” npm package which would list all sub-packages as optional dependencies

How to run the binary:

  1. Use JS wrapper which would call actual executable with exec, spawn, etc.
  2. On installation figure out where Node puts binaries and overwrite it with your binary from the package
  3. Use JS script to call node binding (*.node) or WASM

Tools and blog posts:

namedistributionexecution
binary-install11 (spawnSync)
binwrap11 (spawn)
bin-wrapper11 (spawn, …)
prebuild-install13
blog.xendit.enginee22
hspak.dev22
prebuildify23
blog.orhun.dev31 (spawnSync)
napi-rs33

Example projects:

namedistributionexecution
odiff22
@astrojs/compiler2 (WASM)3
esbuild31 (execFileSync)
biome31 (spawnSync)
Turborepo31 (execFileSync)
lightningcss33

Read more: Distributing CSS in npm package, JavaScript key-value store