Performance Zone is brought to you in partnership with:

Patrick Debois has been working on closing the gap between development and operations for many years. In 2009 he organized the first devopsdays.org conference and since then the world is stuck with the term 'devops'. Always seeking for opportunities to optimize the global IT instead of local optimizations. Patrick is a DZone MVB and is not an employee of DZone and has posted 39 posts at DZone. You can read more from them at their website. View Full User Profile

Compiling a nodejs projects as a single binary

05.16.2013
| 8253 views |
  • submit to reddit

Let's face it, if you write software it's often hard to distribute it: you have the runtime , the modules you depend on and your software itself. Sure you can package that all but packages ofter require you to have root-privileges to install.

Therefore at times it's convenient to have a single file/binary distribution. Download the executable and run it. For ruby project you can convert things into a single jar using Jruby. A good example is the logstash project: download 1 file , run it and you're in business. But you'd still require the java runtime to be installed. (thanks Apple, NOT).

This is a extra of the GO language but I was looking for a similar thing for nodejs. And the following documentation is the closest I could it get: (it works!)

Compiling plain javascript (no external modules)

Enter nexe a tool to compile nodejs projects to an executable binary.

The way it works is: - it downloads the nodejs source of your choice - it creates a single file nodejs source (using sardines ) - it monkey patches the nodejs code to include this single file in the binary (adding it to the lib/nexe.js directory)

Creating a binary is as simple as:

$ nexe -i myproject.js -o myproject.bin -r 0.10.3

Caveats:

Alternatives:

Embedding a native module (in the nodejs binary)

Many of these single packaging tools, suffer from the problem of handline native modules.

nexe doesn't handle native modules (yet).

But with a little persistance and creativity, this is what I did to add the pty.js native module directly to the nodejs binary

$ tar -xzvf node-v0.8.21.tar.gz
$ cd node-v0.8.21

# Copy the native code in the src directory
# If there is a header file copy/adapt it too
$ cp ~/dev/terminal.js/node_modules/pty.js/src/unix/pty.cc src/node_pty.cc

# Correct the export name of the module
# Add the node_ prefix to the node_module name
# Last line should read - NODE_MODULE(node_pty, init)

# add node_pty to src/node_extensions.h (f.e. right after node_zlib)
# NODE_EXT_LIST_ITEM(node_pty)

# Copy the pty.js file
$ cp ~/dev/pty.js/lib/pty.js lib/pty.js

# Add the pty.js to the node.gyp
# Somewhere in the library list add pty.js
# Somewhere in the source list add node_pty.cc

# Adapt the namings/bindings in lib/pty.js
# 1) replace: var pty = require('../build/Release/pty.node');
#    with: var binding = process.binding('pty');
# 2) replace all references to pty. to binding.

$ make clean
$ ./configure
$ make

Now you have a custom build node in out/Release/node The filesize was about 10034856 , you can further strip it and 6971192 (6.6M)

Now you need to remove the native dependency from your package.json before you nexe build it

Packaging the file

A single binary now makes it easy to to make a curl installer from it as it only requires you to download file. Remember the caveat of this.

And you can still package it up:

Extras

Rant about why it's a good or bad Idea - Secure Nodejs distribution

More info on the process.binding:

Convert nodejs projects to single file/beautifier:

Cross compiling:

Published at DZone with permission of Patrick Debois, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)