Native Addon Loader
require-addon (version 1.2.0) is a JavaScript utility designed to facilitate the loading of native C++ addons (typically compiled as `.node` files) across various JavaScript runtimes. Its primary function is to extend the standard CommonJS `require` function by adding an `.addon` method. This package simplifies the complex process of locating and loading precompiled or dynamically compiled native modules, particularly in environments beyond standard Node.js, such as the 'bare' engine utilized within the Holepunch/Hypercore ecosystem. It aims to provide a standardized interface for consuming native bindings, abstracting away some of the underlying system-specific calls and linking complexities. The package's release cadence appears to be infrequent, which is common for foundational libraries serving a specific, critical infrastructure role. Its key differentiator is its cross-runtime compatibility, making it suitable for specialized environments where direct native module integration is essential.
Common errors
-
TypeError: require.addon is not a function
cause Attempted to call `require.addon()` before assigning the module's export to `require.addon`.fixEnsure `const addonLoader = require('require-addon'); require.addon = addonLoader;` is executed before any calls to `require.addon(...)`. -
Error: The specified module could not be found.
cause The native `.node` file for the addon is either missing, not in the expected path, or incompatible with the current runtime (e.g., wrong architecture, Node.js ABI mismatch).fixVerify the native addon is correctly compiled for your system (OS, architecture, Node.js version) and located in the directory passed to `require.addon`. Rebuild the addon if necessary. -
SyntaxError: Named export 'default' not found (module 'file:///path/to/node_modules/require-addon/index.js')
cause Attempting to import `require-addon` using ESM `import` syntax in a pure ESM context, whereas `require-addon` is a CommonJS module.fixUse CommonJS `require()` syntax: `const addonLoader = require('require-addon');`. In strict ESM, consider `import { createRequire } from 'module'; const require = createRequire(import.meta.url); const addonLoader = require('require-addon');` although the global `require.addon` modification might still be problematic.
Warnings
- breaking This package modifies the global `require` object by adding an `.addon` property. This can lead to conflicts with other libraries that also modify global built-ins or introduce unexpected behavior in complex module environments.
- gotcha Native addons (`.node` files) are highly platform-specific and must be compiled for the exact target architecture, operating system, and Node.js ABI (Application Binary Interface) version. Errors often manifest as obscure runtime crashes or 'module not found' issues.
- gotcha The package is written in CommonJS and designed to integrate with `require()`. While Node.js can sometimes load CommonJS modules from ESM, directly using `import ... from 'require-addon'` for its primary functionality is not supported and can lead to errors.
- gotcha The `package.json` specifies an `engines.bare` requirement of `>=1.10.0`. Using this package in the Bare engine runtime below this version may result in undefined behavior or errors.
Install
-
npm install require-addon -
yarn add require-addon -
pnpm add require-addon
Imports
- require('require-addon')
import addonLoader from 'require-addon';
const addonLoader = require('require-addon'); - require.addon
import { addon } from 'require-addon';const addonLoader = require('require-addon'); require.addon = addonLoader; const bindings = require.addon('.', __filename); - bindings (the loaded native module)
const addonLoader = require('require-addon'); require.addon = addonLoader; const bindings = require.addon('.', __filename);
Quickstart
// This example demonstrates how to set up and use require-addon
// to load a native C++ module, typically compiled to a .node file.
// For a real scenario, you would have a precompiled native addon
// in your project structure.
// Step 1: Import the require-addon module using CommonJS syntax.
// The package is designed to extend the global 'require' object.
const addonLoader = require('require-addon');
// Step 2: Assign the imported function to require.addon.
// This makes the native addon loading utility available globally via 'require'.
require.addon = addonLoader;
// Step 3: Load the native addon.
// The first argument is the path to the addon's directory (often '.', meaning current directory).
// The second argument is typically __filename, providing context for resolving relative paths.
// This call will attempt to find and load the appropriate .node file for the current platform and architecture.
try {
const bindings = require.addon('.', __filename);
console.log('Native addon loaded successfully!');
// Here, 'bindings' would be an object exposing functions from your C++ addon.
// For example, if your addon had a 'hello' function:
// console.log(bindings.hello()); // Assuming it returns a string like "Hello from C++!"
console.log('Bindings object:', bindings);
// In a real application, you would now call methods on the 'bindings' object.
} catch (error) {
console.error('Failed to load native addon:', error.message);
console.error('Ensure your native addon is correctly compiled and located.');
}
// To make this runnable, you would need an actual native addon compiled.
// This snippet primarily shows the API usage.