Platinum Partner
architects,high-perf,performance,tips and tricks,node.js

Compiling a nodejs projects as a single binary

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 {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}