-
Notifications
You must be signed in to change notification settings - Fork 4
Using N API
N-API (also written as Node-API) is Node's stable C ABI for native addons. Unlike traditional V8/nan.js bindings, an N-API addon compiled against API level N loads on any runtime that supports level N or higher — without recompilation when Node bumps its major version.
For binary distribution this is a major matrix collapse. Where a V8-based addon has to ship platform x arch x Node-ABI binaries (typically 30–40 per release), an N-API addon ships platform x arch x N-API-level (typically 6–10).
In your addon's package.json:
{
"scripts": {
"save-to-github": "save-to-github-cache --artifact build/Release/your-addon.node --napi 8",
"install": "install-from-cache --artifact build/Release/your-addon.node --napi 8 || node-gyp rebuild"
}
}The asset filename for --napi 8 is:
${prefix}${platform}-${arch}-napi-v8${suffix}
For example: re2-linux-x64-napi-v8.node.br.
When --napi is not specified, the bin falls back to the legacy ABI slot (process.versions.modules) — exactly as before. The two modes are mutually exclusive per build; pick one or the other in your package.json scripts.
Pick the lowest N-API level that has all the APIs your code uses. The lower you target, the wider the runtime support — and since N-API is forward-compatible, a binary targeting level 8 keeps working on any newer Node, Bun, or Deno that supports level 8 or higher.
| N-API level | Minimum Node | Notes |
|---|---|---|
| 1 | 8.6 | MVP. Effectively unused today. |
| 4 | 10.16 | Buffer, threadsafe-functions. |
| 6 | 14.0 | BigInt, dates, accessors. |
| 8 | 16.0 | Object freezing, instanceof improvements. Sensible floor for new projects. |
| 9 | 18.17 | Symbol APIs, finalizer ordering. |
| 10 | 22.0 | Async cleanup hooks, latest property descriptors. |
(Always check Node's official version matrix — it's authoritative; this table is a quick reference.)
If you're not sure, 8 is a safe default. It's been around since Node 16, gets you everything most addons need, and Node 16 itself has been EOL since 2023, so anyone running supported Node already has it.
| Runtime | N-API support | Notes |
|---|---|---|
| Node 18+ | Full | Recommended target; what this package's engines.node requires. |
| Bun 1.0+ | Full | Reads process.versions.napi; identical asset paths work. |
| Deno 2.0+ | Best-effort | Deno's N-API is reasonably stable but evolving. Identical asset paths should work; report issues if they don't. |
| Electron | Use prebuildify
|
This package doesn't yet emit Electron-specific filenames. File an issue if you need it. |
The downloader itself doesn't gate on runtime — it sniffs process.platform / process.arch, downloads the matching napi-v${level} asset, and lets the addon's own load path do whatever runtime check it needs. If the running Node/Bun/Deno doesn't support the declared N-API level, the binary fails to load → verify-build fails → the install falls through to npm run rebuild (which will likely also fail with a useful compiler-side error). That's the intended behavior — the same fallback chain that's been in place since 1.0.
Following the same convention as --host / --host-var / DOWNLOAD_HOST:
| Direct | Env var (default name) | Env var (custom name) | |
|---|---|---|---|
| install | --napi 8 |
DOWNLOAD_NAPI=8 |
--napi-var MYPKG_NAPI then MYPKG_NAPI=8
|
| save | --napi 8 |
DOWNLOAD_NAPI=8 |
--napi-var MYPKG_NAPI then MYPKG_NAPI=8
|
Precedence (highest first):
-
--napi <level>flag - Env var named by
--napi-var <NAME> -
DOWNLOAD_NAPIenv var (default fallback) -
npm_config_platform_napi(advanced; see "Cross-builds" below) - Nothing → fall back to legacy ABI slot
For libraries published to npm, prefer --napi-var YOURPKG_NAPI so consumers can override per-package without colliding with DOWNLOAD_NAPI for other addons in the same node_modules. This mirrors the existing --host-var / --skip-path-var / --skip-ver-var / --agent-var convention.
install-from-cache sniffs platform/arch from the running runtime. If you're trying to populate a node_modules for a different target than the build machine (e.g., building a multi-arch Docker image with layers), the existing npm_config_platform / npm_config_platform_arch overrides apply — and npm_config_platform_napi is the N-API-mode equivalent.
In practice this is fragile (the addon's verify-build won't be able to test the foreign binary) and usually means you should be doing a real per-platform CI build instead. We document the override for symmetry; we don't recommend it.
A typical N-API build matrix in .github/workflows/build.yml:
strategy:
matrix:
include:
- {os: ubuntu-latest, target: linux-x64}
- {os: ubuntu-latest, target: linux-arm64, cross: true}
- {os: macos-latest, target: darwin-x64}
- {os: macos-latest, target: darwin-arm64}
- {os: windows-latest, target: win32-x64}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
- run: npm ci
- run: npm run rebuild # builds your-addon.node for the runner's platform
- run: npm run save-to-github # uploads with --napi 8 -> linux-x64-napi-v8.node.{br,gz}
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}For musl Linux (Alpine), add a separate job using a musl-based container:
- name: Build linux-musl
runs-on: ubuntu-latest
container: node:24-alpine
steps: [...]The bin auto-detects musl via getconf / ldd and tags the asset name accordingly (linux-musl-x64-napi-v8.node.br).
- Install-from-cache — the install bin's full reference, including all flags and env vars.
- Save-to-GitHub-cache — the upload bin's reference.
- Node-API documentation — official spec.
-
node-addon-api— recommended C++ wrapper for writing N-API addons.