node-addon-examples
Node.js C++ addon examples from http://nodejs.org/docs/latest/api/addons.html
Top Related Projects
A framework for building compiled Node.js add-ons in Rust via Node-API
Module for using Node-API from C++
Native Abstractions for Node.js
Node.js native addon build tool
:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS
A modern runtime for JavaScript and TypeScript.
Quick Overview
The nodejs/node-addon-examples repository is a collection of sample projects demonstrating how to create native addons for Node.js. It provides examples of using various tools and techniques to build C++ addons that can be used in Node.js applications, showcasing different binding methods and use cases.
Pros
- Comprehensive set of examples covering multiple binding methods (N-API, node-addon-api, nan)
- Well-organized structure with separate directories for each example
- Includes both simple and complex examples, catering to different skill levels
- Regularly updated to keep pace with Node.js and addon development best practices
Cons
- May be overwhelming for beginners due to the large number of examples
- Some examples might become outdated as Node.js and related tools evolve
- Limited documentation within each example, requiring users to have prior knowledge
- Focuses primarily on C++ addons, with less coverage for other languages
Code Examples
- Simple addon using N-API:
#include <node_api.h>
napi_value Method(napi_env env, napi_callback_info args) {
napi_value greeting;
napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &greeting);
return greeting;
}
napi_value init(napi_env env, napi_value exports) {
napi_value fn;
napi_create_function(env, nullptr, 0, Method, nullptr, &fn);
napi_set_named_property(env, exports, "hello", fn);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, init)
This example creates a simple addon that exports a function hello()
which returns the string "world".
- Using node-addon-api:
#include <napi.h>
Napi::String Method(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, "world");
}
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(addon, Init)
This example achieves the same functionality as the previous one but uses the node-addon-api wrapper for easier development.
- Asynchronous addon using N-API:
#include <node_api.h>
#include <uv.h>
struct AsyncData {
napi_async_work work;
napi_deferred deferred;
int result;
};
void ExecuteWork(napi_env env, void* data) {
AsyncData* async_data = (AsyncData*)data;
// Simulate async work
uv_sleep(1000);
async_data->result = 42;
}
void WorkComplete(napi_env env, napi_status status, void* data) {
AsyncData* async_data = (AsyncData*)data;
napi_value result;
napi_create_int32(env, async_data->result, &result);
napi_resolve_deferred(env, async_data->deferred, result);
napi_delete_async_work(env, async_data->work);
delete async_data;
}
napi_value CreateAsyncWork(napi_env env, napi_callback_info info) {
napi_value promise;
AsyncData* async_data = new AsyncData;
napi_create_promise(env, &async_data->deferred, &promise);
napi_create_async_work(env, nullptr, nullptr, ExecuteWork, WorkComplete, async_data, &async_data->work);
napi_queue_async_work(env, async_data->work);
return promise;
}
napi_value Init(napi_env env, napi_value exports) {
napi_value fn;
n
Competitor Comparisons
A framework for building compiled Node.js add-ons in Rust via Node-API
Pros of napi-rs
- Written in Rust, offering better performance and memory safety
- Provides a higher-level abstraction for Node.js addon development
- Supports automatic generation of TypeScript declarations
Cons of napi-rs
- Steeper learning curve for developers not familiar with Rust
- Less extensive documentation compared to node-addon-examples
- Smaller community and ecosystem
Code Comparison
node-addon-examples (C++):
#include <napi.h>
Napi::String Method(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, "world");
}
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(addon, Init)
napi-rs (Rust):
#[macro_use]
extern crate napi_derive;
#[napi]
fn hello() -> String {
"world".to_string()
}
The napi-rs example demonstrates a more concise syntax and leverages Rust's type system, while the node-addon-examples code shows the traditional C++ approach with explicit Node-API calls.
Module for using Node-API from C++
Pros of node-addon-api
- Provides a higher-level C++ API, making it easier to write native addons
- Offers better type safety and exception handling
- Simplifies memory management with automatic object lifetime tracking
Cons of node-addon-api
- May have a slight performance overhead compared to direct N-API usage
- Requires learning a new API, which might be challenging for developers familiar with V8 API
Code Comparison
node-addon-examples (using N-API directly):
napi_value Create(napi_env env, napi_callback_info info) {
napi_status status;
napi_value result;
status = napi_create_int32(env, 42, &result);
return result;
}
node-addon-api:
Napi::Value Create(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::Number::New(env, 42);
}
The node-addon-api example is more concise and easier to read, with built-in error handling. The node-addon-examples code using N-API directly requires more verbose error checking (not shown in this brief example) and manual resource management.
Native Abstractions for Node.js
Pros of nan
- Provides a higher-level abstraction for writing native addons
- Offers compatibility across multiple Node.js versions
- Includes a rich set of helper functions and macros
Cons of nan
- Requires additional dependency in projects
- May have a steeper learning curve for beginners
- Performance overhead due to abstraction layer
Code Comparison
nan:
NAN_METHOD(SayHello) {
info.GetReturnValue().Set(Nan::New("Hello").ToLocalChecked());
}
NAN_MODULE_INIT(Init) {
Nan::Set(target, Nan::New("sayHello").ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(SayHello)).ToLocalChecked());
}
NODE_MODULE(addon, Init)
node-addon-examples:
napi_value SayHello(napi_env env, napi_callback_info info) {
napi_value greeting;
napi_create_string_utf8(env, "Hello", NAPI_AUTO_LENGTH, &greeting);
return greeting;
}
NAPI_MODULE_INIT() {
napi_value fn;
napi_create_function(env, nullptr, 0, SayHello, nullptr, &fn);
napi_set_named_property(env, exports, "sayHello", fn);
return exports;
}
node-addon-examples focuses on demonstrating various approaches to creating native addons, including N-API and node-addon-api. It provides a wide range of examples for different use cases and serves as a learning resource. nan, on the other hand, is a compatibility layer that simplifies native addon development across Node.js versions but may introduce some overhead.
Node.js native addon build tool
Pros of node-gyp
- Widely adopted and well-established build system for native Node.js addons
- Supports cross-platform compilation and multiple Node.js versions
- Integrates seamlessly with npm for easy distribution of native modules
Cons of node-gyp
- Steeper learning curve for beginners compared to simpler examples
- Requires Python and C++ build tools, which can be challenging to set up
- More complex configuration for advanced use cases
Code Comparison
node-gyp (binding.gyp):
{
"targets": [
{
"target_name": "addon",
"sources": [ "addon.cc" ]
}
]
}
node-addon-examples (binding.gyp):
{
"targets": [
{
"target_name": "example",
"sources": [ "example.cc" ]
}
]
}
The code structure is similar, but node-addon-examples focuses on providing simpler, more digestible examples for learning purposes, while node-gyp is a full-fledged build system with more advanced capabilities.
node-gyp is better suited for production-ready modules and complex projects, while node-addon-examples is ideal for learning and understanding the basics of native addon development in Node.js.
:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS
Pros of Electron
- Enables cross-platform desktop app development using web technologies
- Large ecosystem with extensive documentation and community support
- Integrates Chromium and Node.js, providing a rich set of APIs
Cons of Electron
- Larger application size due to bundled Chromium engine
- Higher memory usage compared to native applications
- Potential security concerns due to full system access
Code Comparison
Electron (main process):
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
Node-addon-examples (N-API C++ addon):
#include <napi.h>
Napi::String Method(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, "world");
}
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(addon, Init)
Node-addon-examples focuses on creating native addons for Node.js, providing low-level access and performance benefits. It's ideal for extending Node.js functionality with C++ modules. Electron, on the other hand, is a framework for building desktop applications using web technologies, offering a higher-level abstraction and easier cross-platform development at the cost of increased resource usage.
A modern runtime for JavaScript and TypeScript.
Pros of Deno
- Built-in TypeScript support without additional configuration
- Improved security with permissions system
- Modern JavaScript features and APIs out of the box
Cons of Deno
- Smaller ecosystem and fewer third-party modules compared to Node.js
- Limited compatibility with existing Node.js projects and packages
Code Comparison
Deno:
import { serve } from "https://deno.land/std@0.140.0/http/server.ts";
serve((req) => new Response("Hello, World!"));
Node-addon-examples:
const addon = require('./build/Release/addon');
console.log(addon.hello());
Key Differences
- Deno focuses on modern JavaScript and TypeScript, while node-addon-examples demonstrates C++ addon integration with Node.js
- Deno emphasizes security and standardization, whereas node-addon-examples showcases low-level system access and performance optimization
- Deno's module system is URL-based, while node-addon-examples relies on Node.js's CommonJS module system
Use Cases
- Deno: Web applications, APIs, and scripts leveraging modern JavaScript features
- Node-addon-examples: Performance-critical applications, system-level integrations, and projects requiring native extensions
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Node.js Addon Examples
A repository of Node.js Addons examples.
Implementations of examples are named either after Node.js versions (node_0.10
,
node_0.12
, etc), or Node.js addon implementation APIs:
nan
: C++-based abstraction between Node and direct V8 APIs.Node-API
: C-based API guaranteeing ABI stability across different node versions as well as JavaScript engines. (Node-API was previously known as N-API.)node-addon-api
: header-only C++ wrapper classes which simplify the use of the C-based Node-API.node-addon-api-addon-class
: Similar tonode-addon-api
, but deriving from theNapi::Addon
class. 1_hello_world provides an example.
Implementations against unsupported versions of Node.js are provided for completeness and historical context. They are not maintained.
The examples are primarily maintained for Node-API and node-addon-api and as outlined in the Node.js documentation, unless there is a need for direct access to functionality which is not exposed by Node-API, use Node-API.
The Node-API Resource offers an
excellent orientation and tips for developers just getting started with Node-API
and node-addon-api
.
Usage
The directory structure is as follows:
REPO_ROOT
âââ test_all.js
âââ package.json
âââ README.md
âââ src
âââ 1-getting-started
â âââ example1
â â âââ nan
â â âââ node-addon-api
â â âââ napi
â âââ example2
â âââ example3
âââ 2-js-to-native-conversion
âââ 3-context-awareness
âââ 4-references-and-handle-scope
âââ 5-async-work
âââ 6-threadsafe-function
âââ 7-events
âââ 8-tooling
In each example's implementation subdirectory, run
npm install
node ./
to see the example in action.
Top Related Projects
A framework for building compiled Node.js add-ons in Rust via Node-API
Module for using Node-API from C++
Native Abstractions for Node.js
Node.js native addon build tool
:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS
A modern runtime for JavaScript and TypeScript.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot