Native addons & N-API in nodejs

advance · Node.js — Server-side JavaScript

N-API (now officially called Node-API ) is a C API for building native Node.js Addons. It is designed to insulate the native code from changes in the underlying JavaScript engine (V8), allowing your compiled C/C++ code to run across different versions of Node.js without needing to be recompiled. 1. Why do we need Node-API? Before Node-API, developers used the native V8 headers directly. However, the V8 engine changes frequently. If you wrote a native module for Node.js 10 and upgraded to Node.js 12, your module would likely crash or fail to compile because the internal V8 functions had changed. Node-API provides an ABI (Application Binary Interface) stability guarantee: Compile Once, Run Everywhere: A module compiled against Node-API for Node.js 10 will continue to work in Node.js 20+ without modification. Engine Agnostic: It allows Node.js to potentially swap V8 for another engine (like Microsoft’s Chakra) without breaking native addons. 2. When should you use it? Native addons are generally used for three reasons: Performance: Heavy computation (image processing, video encoding, cryptography) that C++ handles faster than JavaScript. Legacy Libraries: You need to use an existing C/C++ library that doesn't have a JavaScript equivalent. Low-level System Access: Accessing hardware or OS features that are not exposed by the Node.js standard library. 3. Key Concepts A. Opaque Data Types In Node-API, you don't interact with V8 objects directly. Instead, you use opaque types like napi_value . This is a "handle" that represents a JavaScript value (a string, number, or object) inside your C code. B. The Environment ( napi_env ) Every Node-API function requires a napi_env . This represents the "context" of the JavaScript engine and is used to manage the lifecycle of values and handle exceptions. C. node-addon-api (C++ Wrapper) While Node-API is written in C, most developers prefer the node-addon-api module. This is a header-only C++ wrapper that makes the code look more modern and easier to read using classes and exceptions. 4. A Simple Example (C++) Using the node-addon-api wrapper to create a "Hello World" function: #include <napi.h> // The actual C++ logic Napi::String Method(const Napi::CallbackInfo& info) {   Napi::Env env = info.Env();   return Napi::String::New(env, "Hello from C++!"); } // Initialization: Registering the function Napi::Object Init(Napi::Env env, Napi::Object exports) {   exports.Set(Napi::String::New(env, "hello"), Napi::Function::New(env, Method));   return exports; } NODE_API_MODULE(hello_addon, Init) 5. Comparison: JS vs. C++ Addon  Feature  JavaScript  Node-API (C/C++)  Development Speed  Very Fast  Slow (Manual memory management)  Execution Speed  Fast (JIT optimized)  Extremely Fast (Raw CPU)  Memory Control  Managed (Garbage Collector)  Manual (Malloc/Free)  Crashing  Throws an Exception  Segfault (Crashes the whole process) 6. How to Build Native Addons To turn your C++ code into a .node file that JavaScript can require() , you use a tool called node-gyp . Write code: Create your .cpp file. Configure: Create a binding.gyp file (JSON-like config). Build: Run node-gyp configure build . Use: const addon = require('./build/Release/hello_addon'); 7. Modern Recommendation: Wasm? For many performance tasks today, developers are moving toward WebAssembly (Wasm) instead of Node-API. Wasm is almost as fast as native C++, but it is safer (sandboxed) and easier to distribute because it doesn't require the user to have a C++ compiler installed on their machine.

Back to Node.js — Server-side JavaScript

Browse all study material on Careeroza