Background
When building full-stack JavaScript application, the need to let JavaScript to talk to a C or C++ API may arises due to the following reasons:
- The operating system, database or other native software only provide API to C or C++.
- The code is CPU-intensive such that using C or C++ to compute will provide a performance boost comparing to implementing in JavaScript.
- etc...
Thus, we may consider to use C++ to write a native addon for JavaScript.
What is a native addon?
Native addon is essencially a DLL (Dynamically Linked Library) which also
called SO (Shared Object) on Linux. It can be loaded in the runtime by a
program. Specifically, it can be used as a normal Node module through
require()
or import
as it exposes an API that is capatible with your
JavaScript environment. The compiled native addon usually has a .node
extension.
Ways to write a native addon
1. Direct Use of Internal V8, libuv and Node.js Libraries
Node.js and its libraries (e.g. V8, libuv, OpenSSL and etc.) provides APIs
through their header file. These files are located at /include/node/
folder of
your Node.js installation location. You can directly calling these APIs to write
the module using C++ as V8, the core of Node.js, is written in C++. However, the
module will be tightly dependent to the internal implementation of the Node.js
and other libraries. As the implementation of these dependencies may change, it
may break the ABI stability. Eventually, whenever the Node.js released a new
version, the native module you build with the old version of Node.js headers may
not be capatible.
You can learn more about ABI stability on Node.js official documentation .
Examples of using this approach can be found at here .
2. NAN
To solve the ABI stability problem mentioned above, the NAN project ( https://github.com/nodejs/nan ) appears. This project abstracts the internal implementation of Node.js and the V8 engine by adding C++ wrappers and marcos around their APIs. However, NAN project does not completely abstract V8 API and does not provide full support for all the libraries used inside Node.js. Besides, the NAN project was maintained independently from the Node.js project which means whenever a new Node.js version releases, we have to wait NAN to add support for such new version before users can use our native addon. On the good side though, it can support a lot of Node.js versions especially the old ones like 0.8, 0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 and 18 (as of Aug 2022).
Examples of using this approach can be found at
here
or
here
(under nan
folder of
each example).
3. N-API (Node-API)
To solve the maintainance problem, the N-API apperars as the successor of NAN.
It is writen in C and maintained as a part of the Node.js project itself. It
provides an abstraction layer that abstracts internal implementation of Node.js
and its libraries. The API is defined in the headers node_api.h
and
node_api_types.h
, and provides a forward compatibility guarantee that crosses
the Node.js major version boundary.
Besides solving the problem above, N-API is also independent from the underlaying JavaScript runtime (e.g. V8) and allows Node.js to switch to other JavaScript engines like Chakra ( https://github.com/chakra-core/ChakraCore ) which eventually builds Node.js on ChakraCore ( https://github.com/nodejs/node-chakracore ).
However, please note that Node.js introduced N-API in version 8.6.0 and marked it as a stable component of the project as of Node.js 8.12.0, which means it is not possible to use N-API to support Node.js version before 8.6.0.
You can learn more about N-API on an article write by Node.js officials here , or on offical Node.js documentation here and here .
Examples of using this approach can be found at
here
(under napi
folder of
each example).
4. node-addon-api
As the C API in N-API is little bit hard to use, the node-addon-api module ( https://github.com/nodejs/node-addon-api ) contains header-only wrappers of the N-API in C++. It provides a C++ object model and exception handling semantics with low overhead according to its README file.
Please also note that, as also mentioned in the README file, node-addon-api
module is not part of Node.js, but it preserves the benefits of the Node-API as
it consists only of inline code that depends only on the stable API provided by
Node-API. As such, modules built against one version of Node.js using
node-addon-api should run without having to be rebuilt with newer versions of
Node.js.
Examples of using this approach can be found at
here
(under node-addon-api
folder of each example).