Create Native NodeJS Modules Fallbacking To Emscripten Ones
If you're a frontend developper, you probably already heard about icon fonts. If you use the Gulp build tool, you maybe already used gulp-iconfont. As its maintainer, when i heard about the WOFF2 font format, i really wanted to get it in output of my gulp plugin.
NodeJS C++ add-on: easy!
Creating a NodeJS add-on was blazing fast. The build system is incredibly well documented and works like a charm.
Typically when creating a native add-on you need to create a wrapper written in C++ that glue the library you want to use to the V8 engine. Mine is pretty simple. It indeed wraps the Google's woff2 project encoding function. This C++ function signature:
bool ConvertTTFToWOFF2( const uint8_t *data, size_t length, uint8_t *result, size_t *result_length );
becomes this NodeJS one:
output:Buffer function ttf2woff2(input:Buffer);
Once the wrapper is made, you just have to create a file named binding.gyp that allows you to specify building instruction for the various compilers. We had to struggle a bit with the MacOSX one since i couldn't test by myself.
And that's it! Your module gets compiled at
npm install. In fact,
i had to test a few time and correct compilation errors progressively but it
was suprisingly fast to get it up and running. For that testing matter i
set up a few commands
But what about users whose OS can't build it? How to not let them down?
Emscripten for the win!
Once again, i made
to simplify the build. Basically, it query the
binding.gyp file with
miniquery for the C/C++
files to build, remove the
addon.cc one that we do not want and then set it
as args to the
Gracefully fail compilation
So, now we have our Emscripten build, let's fallback to him when the native NodeJS add-on compilation goes wrong. First, we must ensure that any failure won't impeach the module to install. We're basically doing this by overriding the default installation script to exit with a 0 code whatever result the compiler gives.
It works! But what about browserifying it ?
In order to allow
gulp-iconfont users to preview and download the resulting
fonts made with it (and to see it it was feasible :p), i've made a
full frontend font
builder. So, i immediatly tried to use my shinny new module to also output
The fact is that it doesn't work out of the box. Browserify try to add every NodeJS dependencies that appears to be useless when using the Emscripten module on the front-end side.
Chances are that Browserify allows to skip the parsing for some files. Plus a simple trick to fix the Emscripten require, i've finally been able to make the magic happen.
I'm really impressed by how a C/C++ noob like me have been able to do this in the free time of a few days. If you didn't already, you really should have a look at NodeJS native bindings!