One of the limitations of native addons is that they must be compiled for each target platform and architecture. Without pre-built binaries, every user who installs your package must have a working C/C++ toolchain on their machine.
prebuild solves this by letting you compile binaries ahead of time and publish them as GitHub Releases. When a user installs your package, prebuild-install downloads the right pre-built binary for their platform and Node-API version - falling back to compiling from source only if no matching binary is found.
Node-API support was added to prebuild in version 8.1.0.
node-pre-gyp is an alternative tool that uses Amazon S3 instead of GitHub Releases.
The tooling is split into two packages:
- prebuild - used by you (the addon developer) to build and upload binaries.
- prebuild-install - used by your consumers to download the pre-built binary at install time.
Install prebuild as a dev dependency so it is available during your CI publish workflow:
npm install prebuild --save-devUploading a release asset to GitHub requires a personal access token.
-
Go to GitHub Settings → Developer settings → Personal access tokens.
-
Click Generate new token and choose Fine-grained token (recommended) or classic.
- For a fine-grained token: grant Read and write access to Contents on the target repository.
- For a classic token: select the
public_reposcope (orrepofor private repositories).
-
Copy the generated token - it is only shown once.
-
Set it as an environment variable:
export GITHUB_TOKEN=<your-token>
In CI, store the token as a repository secret and expose it to the workflow via env.
Because prebuild uploads to GitHub, you must declare the repository:
"repository": {
"type": "git",
"url": "https://github.com/yourorg/your-napi-addon.git"
}Consumers need prebuild-install to download pre-built binaries:
"dependencies": {
"prebuild-install": "^7.0.0"
}"scripts": {
"install": "prebuild-install --runtime napi || node-gyp rebuild",
"rebuild": "node-gyp rebuild",
"prebuild": "prebuild --runtime napi --all --strip --verbose",
"upload": "prebuild --runtime napi --upload ${GITHUB_TOKEN}"
}The --runtime napi flag is required for Node-API builds. The --all flag builds for every supported Node-API version declared in the binary property. Without --all or explicit --target flags, prebuild builds only for the Node-API version of the current Node.js process.
Declare which Node-API versions your addon supports:
"binary": {
"napi_versions": [3]
}3 is a reasonable default - it was the Node-API version when the API left experimental status, and binaries built against it run on all later versions.
The NAPI_VERSION preprocessor value must be defined so the Node-API headers configure themselves for the correct version. How you set it depends on your build tool.
In binding.gyp:
"defines": [
"NAPI_VERSION=<(napi_build_version)"
]In CMakeLists.txt:
add_compile_definitions(NAPI_VERSION=${napi_build_version})Build and package your binaries:
npm run prebuildWhen you are ready to publish a release, upload to GitHub:
npm run uploadThis requires GITHUB_TOKEN to be set in the environment. In CI, trigger the upload step only after a version tag is pushed.
When a user runs npm install, the install script in your package.json runs:
prebuild-install --runtime napi || node-gyp rebuildprebuild-install fetches the GitHub Releases page for your repository, finds a binary that matches the user's platform, architecture, and Node-API version, and installs it. If no match is found, node-gyp rebuild compiles from source as a fallback.