DEV Community


Using WebAssembly for a NodeJS Native Addon

gfx profile image FUJI Goro Updated on ・2 min read

Recently I have released an npm @gfx/zopfli, which is a JavaScript binding to google/zopfli, as a drop-in replacement to node-zopfli.

I have a story for this package: it is built with Emscripten into WebAssembly.

WebAssembly is a portable executable format for the web browsers, but it is not only for the web but usable for nodejs native addons. That is, the package includes pre-built executable binary in wasm. No compiler is required to install it. No node-pre-gyp magic is required (in fact node-zopfli has problems with node-pre-gyp pierreinglebert/node-zopfli#87). Even Windows users can use it just by npm install @gfx/zofpli (or yarnpkg add @gfx/zopfli).

You might be worried about wasm performance, but I think it is already production-ready, although it is slower than native code.

Here is a benchmark result in the repo on NodejS 8.9.1 (see benchmark/random-bytes.js for the code):

payload size: 1

universal-zopfli x 106 ops/sec ±0.79% (80 runs sampled)
node-zopfli x 201 ops/sec ±1.99% (82 runs sampled)

payload size: 1024

universal-zopfli x 1.37 ops/sec ±12.99% (11 runs sampled)
node-zopfli x 4.62 ops/sec ±3.34% (27 runs sampled)

payload size: 1038336

universal-zopfli x 0.26 ops/sec ±6.91% (6 runs sampled)
node-zopfli x 0.39 ops/sec ±1.35% (6 runs sampled)

The speed (ops/sec) of universal-zopfli (i.e. in wasm) is about 30% - 70% of node-zopfli (i.e. in native code). It is good enough for production if you use @gfx/zopfli as a Zlib alternative in compression-webpack-plugin. And fortunately, the current state of WebAssembly implementation in NodeJS/V8 is just an MVP! It should be getting better in performance.

Development of nodejs native addon with Emscripten is difficult for now, but I believe most of NodeJS native addons which do not use systemcalls, including nodejs standard libraries such as zlib, can be replaced with wasm because of its portability.

Discussion (0)

Editor guide