Compiling a nodejs projects as a single binary
The Web Dev Zone is brought to you in partnership with Mendix. Discover how IT departments looking for ways to keep up with demand for business apps has caused a new breed of developers to surface - the Rapid Application Developer.
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!)
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
- I had an issue with unicode chars that got converted: it uses uglify.js and this needs to be configured to leave them alone Sardines Patch Unichode . This was necessary to get terminal.js to compile
- Next issue was to get socket.io-client to compile: the swfobject has document and navigator objects, so this had to be fixed as well - Sardines Patch Document & Navigator
- Node-webkit to package nodejs apps that require UI interaction
- http://tidesdk.multipart.net/docs/user-dev/generated/ - seems similar but could not really grasp it
- NPKG - https://github.com/wearefractal/npkg - old but interesting code
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:
- create a rpm, deb, etc.. package from it using fpm
- or create a native MacOSX .app file from it as Matthias Bynens suggest in http://mathiasbynens.be/notes/shell-script-mac-apps
- build a DMG - http://www.recital.com/index.php?option=com_content&view=article&id=108%3Ahowto-build-a-dmg-file-from-the-command-line-on-mac-os-x&Itemid=59
More info on the process.binding:
Convert nodejs projects to single file/beautifier:
- Npk - https://github.com/cfsghost/npk
- UglifyJS - https://github.com/mishoo/UglifyJS/
- RequireJS - http://requirejs.org/
- Browserify - http://browserify.org/
- OneJS - https://github.com/azer/onejs