A skeleton for binding C++ libraries to Node.js using Nan. This is a small, helper repository that generates a Javascript constructor called HelloWorld
. HelloWorld
has a number of methods to demonstrate different ways to use Nan for building particular types of functionality (i.e. asynchronous functions).
Nan is used in many C++ => Node.js port projects, such as node-mapnik, node-osrm, and node-osmium. More examples of how to port C++ libraries to node can be found at nodejs.org/api/addons.html. See https://nodesource.com/blog/c-add-ons-for-nodejs-v4/ for a detailed summary of the origins of Nan.
Why port C++ to Node.js?. That's a great question! C++ is a high performance language that allows you to execute operations without clogging up the event loop. Node.js is single-threaded, which blocks execution. Even in highly optimized javascript code it may be impossible to improve performance. Passing heavy operations into C++ and subsequently into C++ workers can greatly improve the overall runtime of the code.
The skeleton prepares a C++ port to Node.js and provides the following for quick development:
- Tests: created with Tape in the
test/
directory. Travis CI file is prepared to build and test your project on every push. - Documentation: uses documentation.js to generate API documentation from JSDOC comments in the
.cpp
files. Docs are located inAPI.md
. - Build system: node-pre-gyp generates binaries with the proper system architecture flags
- Publishing: Structured as a node module with a
package.json
that can be deployed to NPM's registry.
This repository itself can be cloned and edited to your needs.
git clone [email protected]:mapbox/node-cpp-skel.git
cd node-cpp-skel
make # build binaries
make test
Note: by default the build errors on compiler warnings. To disable this do:
WERROR=false make
Code coverage is critical for knowing how well your tests actually test all your code. To see code coverage you can view current results online at or you can build in a customized way and display coverage locally like:
make coverage
For more details about what make coverage
is doing under the hood see https://github.com/mapbox/cpp#code-coverage
If you're developing on macOS and have Xcode installed, you can also type make xcode
to generate and open an Xcode project. In the dropdown, choose npm test
to run the npm tests. You can also add more targets by adding the appropriate lines in Makefile
, and rerunning make xcode
. If you are modifying binding.gyp
, e.g. by adding more source files, make sure to rerun make xcode
so that Xcode knows about the new source files.
var HelloWorld = require('./path/to/lib/index.js');
var HW = new HelloWorld();
var hi = HW.wave();
console.log(hi); // => howdy world!
It's a good idea to publish pre-built binaries of your module if you want others to be able to install it properly on their own systems, which can very likely not have a compiler like gcc
or clang
. Node-pre-gyp does a lot of the heavy lifting for us (like detecting which system you are building on and deploying to s3) but you'll need a few things configured to get started.
- In the
package.json
, update the"binary"
field to the appropriate s3 buckethost
. - If you plan on publishing binaries via Travis-CI, setup your AWS security credentials in the
.travis.yml
- this gives the travis environment the proper access to the bucket named above.
Publishing on Travis CI
This project includes a script/publish.sh
command that builds binaries and publishes them to s3. This script checks your commit message for either [publish binary]
or [republish binary]
in order to begin publishing. This allows you to publish binaries according to the version specified in your package.json
like this:
git commit -m 'releasing 0.1.0 [publish binary]'
Republishing a binary overrides the current version and must be specified with [republish binary]
.
Adding new operating systems and node versions
The .travis.yml
file uses the matrix
to set up each individual job, which specifies the operating system, node version, and other environment variables for running the scripts. To add more operating systems and node versions to the binaries you publish, add another job to the matrix like this:
- os: {operating system}
env: NODE="{your node version}" TARGET="Release"
install: *setup
script: *test
after_script: *publish