In this article we will talk about the most important concepts of developing native extensions for Node.js. In particular, here will be considered a practical example of creating such an extension, which may well be your first project in this area.

Basics of developing native extensions for Node.js
If you briefly talk about native extensions for Node.js, you can note that they represent a kind of logic implemented in C ++ that can be called from JavaScript code. Here it is worthwhile to clarify the features of Node.js and consider the component parts of this platform. It is important to know that, in the context of Node.js, we can talk about two languages ​​- JavaScript and C ++. All this can be described as:
- JavaScript is a programming language in which projects are written under Node.js.
- V8 is a JS-code engine.
- Libuv is a C library that implements asynchronous code execution.
Where are the native extensions in this scheme? Consider this on the example of operations to work with the disk. Access to the disk subsystem is not included in the capabilities of JavaScript or V8. Libuv provides asynchronous code execution capabilities. However, using Node.js, you can write data to disk and read it. This is where native extensions come to the rescue. The
fs
module is implemented using C ++ tools (it has access to the disk), it gives us methods like
writeFile
and
readFile
that can be called from JavaScript.
')
Interaction with native extensions from JS codeUnderstanding this mechanism, we can take the first steps in developing native extensions. But before doing programming, let's talk about the tools.
Basic tools
BindingFile binding.gyp
This file allows you to customize the compilation options for native extensions. One of the most important things we need to determine is which files will be compiled, and how we will call the finished library. The structure of this file is similar to JSON, it contains the settings of the target (target) and source (sources) for compilation.
NodeTool-gyp tool
The
node-gyp tool is designed to compile native extensions. It is implemented on the basis of Node.js and is available in npm, which allows you to compile the extension with the appropriate command. In response to this command, the system will detect the
binging.gyp
file located in the root directory and proceed to compile the extension.
In addition,
node-gyp
allows, by default, to form release assemblies or assemblies for debugging. As a result, depending on the settings, after compilation, a binary file with the extension
.node
will be created in the
release
or
debug
.node
.
NodeSite-bindings tool
The
node-bindings package allows you to export native extensions. He is responsible for finding the appropriate files in the
build
or
release
folder.
â–ŤAPI n-api
N-api is an API created by C tools that allows you to interact with the engine in an abstract way, independent of the underlying execution environment. In our opinion, this approach is the result of the development of the platform, during which efforts were made to port Node.js to various architectures.
N-api gives stability and compatibility when working with different versions of Node.js. Thus, if a certain native extension was compiled for Node 8.1, you will not need to compile it again for Node 8.6 or 9.3. This simplifies the lives of those involved in supporting or participating in the expansion.
At the moment, n-api is in an
experimental state .
NodeTool-addon-api tool
The
node-addon-api module makes available to the C ++ developer — an implementation of n-api, which will make it possible to use the capabilities of this language.
First steps in the world of native extensions
Note that the Node 9.3 platform is used for this example.
In order to start developing native extensions, we will write the classic “Hello World” application. The idea of ​​this application allows you to implement it with a fairly simple code, not overloaded with additional logic, which will give us the opportunity to focus on the basic structures, to consider the minimum necessary code.
Let's start with the initialization of npm, which will then allow to install dependencies.
npm init
Now install the dependencies.
npm i node-addon-api bindings
At this stage, you need to create a C ++ file containing the extension logic.
#include <napi.h> Napi::String SayHi(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); return Napi::String::New(env, "Hi!"); } Napi::Object init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "sayHi"), Napi::Function::New(env, SayHi)); return exports; }; NODE_API_MODULE(hello_world, init);
In this file there are three important parts that we will consider, starting with the one that is at the bottom of the text.
NODE_API_MODULE
. The first argument is the name of the native extension, the second is the name of the function that initializes this extension.init
. This is the function that is responsible for initializing the extension. Here we have to export the functions that will be called from the JS-code. In order to do this, you need to write the name of the function in the exports
object and specify the function itself that will be called. The init
function should return the exports
object.sayHi
. This function will be executed when calling our native extension from JavaScript.
Now we will create a
binding.gyp
file that will contain the configuration of the native extension.
{ "targets": [ { "cflags!": [ "-fno-exceptions" ], "cflags_cc!": [ "-fno-exceptions" ], "include_dirs" : [ "<!@(node -p \"require('node-addon-api').include\")" ], "target_name": "hello_world", "sources": [ "hello_world.cc" ], 'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ] } ] }
And this is what the JavaScript code looks like in which the extension is connected and working with it is performed.
const hello_world = require('bindings')('hello_world') console.log(hello_world.sayHi());
Now it only remains to compile the extension and run the JS file. Here's what it looks like.
Compiling and using the native extensionHistory of native extensions for Node.js and useful materials
We believe it is useful to talk about the history of native extensions, since studying this question allows us to investigate a large amount of useful documentation and to find many examples. N-api has replaced nan. This abbreviation stands for
Native Abstraction for Node.js. Nan is a C ++ library that does not have the same flexibility as n-api. It allows, in abstract form, to work with V8, but is tied to the release of V8. As a result, there may be V8 changes in new releases of Node.js that may disrupt the workings of native extensions. The solution to this problem is one of the reasons for the emergence of n-api.
Knowledge of the existence of nan allows us to investigate relevant examples and documentation. All this can be a useful source of knowledge for those who study the development of native extensions for Node.js.
Here is a list of useful materials on the development of native extensions for Node:
Results
The author of this material says that studying the development of native extensions for Node.js helped him to better understand the structure of this platform and the features of its operation. There are many scenarios in which such extensions can be useful. Among them is the creation of high-performance applications, the integration of Node.js projects with C / C ++ libraries, or the use of outdated code in such projects. In addition, developing native extensions is a great way to explore the internal mechanisms of Node.js.
Dear readers! Do you use native extensions for Node.js in your projects?
