How to compile node.js to binary release (with native modules)

Viewed 1075

Currently, I’m experimenting with building Node.js projects (different bundlers and other kinds of stuff). And I got a simple idea about bundling Node.js to a single binary for Linux, macOS, or Windows.

There are two packages nexe and pkg both of them don’t really support native .node modules that are used by packages like bcrypt or realm. Were you performing a similar compilation? I would be extremely happy to see some real-world examples (I could not find them on GitHub).

But... for what? It's more like an idea for fun what we're able to archive with Node.js. Even if it will be working (I get it working on cjs packages without native modules) example project with hello wold may have a size above 30MB.

One cool observation is that @vercel/ncc is able to compile my project into a single directory, but it also doesn’t work without node_modules (probably, I had no environment to test it)

Update V1: Building realm is impossible in such kinds of projects, the simplest solution is to not use realm in node apps because it will crash the binary build (it's because realm is using tons of other packages such as electron or react-native which doesn't work at all when it comes to desktop platforms.

My code is available at the following repository: https://github.com/keinsell/typecraft

2 Answers

After days of struggling with researching how pkg works and searching for potential alternatives, I've found caxa which were working for me in a good way, and on the road, I also got pkg working fine with (actually only tested on bcrypt) native modules. My core insights on using pkg for building Node.js binaries are:

  • Use matrix-builds on CI to build package ex. win package from windows host, mac from macos host etc.
  • Be sure to include native modules to assets (there you can use require() function in JavaScript (example below) or use pkg.assets object in package.json - I don't really get it but it's contained in my issue on vercel/pkg - vercel/pkg#1473
+ require('bcrypt/lib/binding/napi-v3/bcrypt_lib.node')

export async function main() { /* ... */ }

Some modules are still build-crashing, and the good example is realm but I'll still search for a way of building it and including it into node.js binary application. All of my progress on researching Node.js builds will be available on https://github.com/keinsell/typecraft and this StackOverflow answer will be updated over time and my new discoveries.

Related