node-pre-gyp ships prebuilt binaries for native Node addons
Node.js tool for easy binary deployment of C++ addons
At a glance
- What is it?
- @mapbox/node-pre-gyp is a BSD-3-Clause JavaScript tool that sits between npm and node-gyp to publish and install prebuilt C++ addon binaries, with S3 hosting, cross-compilation targets and a fallback to source builds. It suits addon maintainers who want users to skip a compiler, and it depends on a host you control.
- Who is it for?
- Adopt node-pre-gyp if you maintain a Node.js native addon and want most users to install a prebuilt binary instead of compiling, and you can run an S3 bucket or equivalent host for the artefacts. Do not adopt it if your addon is not native, since the whole tool is about compiled .node modules.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
It sits between npm and node-gyp, which is the whole idea
@mapbox/node-pre-gyp makes it easy to publish and install Node.js C++ addons from binaries, and the architecture is described in one sentence. It stands between npm and node-gyp and offers a cross-platform method of binary deployment.
The problem it solves is specific to native addons. A package that contains a compiled .node file cannot be installed by npm alone, because the binary has to match the user's platform, architecture, and Node ABI. The default path is to compile from source on the user's machine, which means every user needs a compiler, a toolchain, and the patience to wait for a build that may fail on a platform you have never seen.
node-pre-gyp changes the default. You publish a binary per platform and ABI, and the install step fetches the matching one. The fallback exists, and the README is explicit that you should use it, because a user whose platform you did not build for should compile from source rather than fail.
There are three delivery mechanisms, and they are worth distinguishing. The first is a command line tool called node-pre-gyp that can install your package's C++ module from a binary. The second is a set of developer targeted commands for packaging, testing and publishing binaries. The third is a JavaScript module that can dynamically require your installed binary, exposed as require('@mapbox/node-pre-gyp').find.
That third one matters for a specific reason. A native addon built for a different Node ABI will throw an error when it is required, and finding that error usually means digging through loader internals. A find function that locates the correct binary for the running runtime turns that into a normal code path.
The project is a Mapbox project, and the credits say the module is modeled after node-gyp by Tootallnate, with the motivation for the initial development coming from ErisDS and the Ghost Project.
Ten commands that cover the whole lifecycle of a binary
The command set is small enough to read in one go, and it maps onto the lifecycle of a prebuilt artefact.
clean removes the entire folder containing the compiled.node module. install installs a pre-built binary for the module. reinstall runs clean and install at once. build compiles the module by dispatching to node-gyp or nw-gyp. rebuild runs clean and build at once. package packs the binary into a tarball. testpackage tests that the staged package is valid. publish publishes the pre-built binary. unpublish unpublishes it. And info fetches information about published binaries.
The chaining syntax is worth knowing, because it is how the release pipeline is normally written. The commands can be chained:
node-pre-gyp clean build unpublish publish infoThat single line is a full release cycle, and it is the kind of thing that goes straight into an npm script.
The dispatch in build is the detail that explains how the tool supports more than one runtime. Compiling goes through node-gyp or nw-gyp, and the --runtime option customises it, with node, electron and node-webkit as the valid options. So the same tool publishes binaries for plain Node, for Electron applications and for node-webkit.
The build target also accepts a --target option to pass the target node or node-webkit version to compile against, and --target_arch and --target_platform to override the host values. The valid platform values listed are linux, darwin, win32, sunos, freebsd, openbsd and aix, and the target architecture can be any value supported by Node.js. Those three options together are what makes cross-compilation possible from one machine.
The package.json scripts confirm the intended composition. The test script is tape test/*test.js, the coverage script runs nyc with --all over index.js and lib, and there are separate scripts for updating the ABI crosswalk and for upgrading the vendored node-gyp, both running node scripts. The lint script covers eslint.config.js, bin/node-pre-gyp, the lib and lib/util directories, the tests and the scripts.
The package.json binary object is the configuration surface
Configuring an addon for node-pre-gyp is a package.json exercise, and the README's example shows the whole shape.
"dependencies" : {
"@mapbox/node-pre-gyp": "1.x"
},
"devDependencies": {
"@aws-sdk/client-s3": "3.x"
},
"scripts": {
"install": "node-pre-gyp install --fallback-to-build"
},
"binary": {
"module_name": "your_module",
"module_path": "./lib/binding/",
"host": "https://your_module.s3-us-west-1.amazonaws.com"
}The README breaks down why each part is there. The dependencies list node-pre-gyp. The devDependencies should list @aws-sdk/client-s3 so that you can run node-pre-gyp publish locally or from a CI system, and the recommendation is devDependencies only, because the AWS SDK is large and is not needed for node-pre-gyp install, since install only uses http to fetch binaries. That is a well-reasoned split: the heavy publishing client never ships to your users, only the downloader does.
The scripts section overrides the install target with node-pre-gyp install --fallback-to-build, which allows node-pre-gyp to be used instead of the default npm behaviour of always source compiling with node-gyp directly.
And the binary object describes the key properties you provide to allow node-pre-gyp to package optimally. The host is the URL the binaries are served from, and the example uses an S3 bucket endpoint. There is an --acl option to set the S3 ACL when publishing binaries, for example public-read or private, which overrides the binary.acl setting in package.json.
The README also records a piece of history that matters if you are following an old guide. It says that in the past the project recommended putting @mapbox/node-pre-gyp in the bundledDependencies, but no longer does, because of old npm bugs with Node 0.10.x that could stop node-pre-gyp from being available at the right time during install. It also mentions a preinstall script approach that was recommended as an alternative, which it now advises against.
build-from-source can target one module inside a larger dependency tree
One option in the README deserves a section of its own, because it solves a problem that anyone who publishes native addons will recognise.
Both --build-from-source and --fallback-to-build can be passed alone or they can provide values, and you can pass --fallback-to-build=false to override the option as declared in package.json. Beyond simply passing --build-from-source, you can also pass --build-from-source=myapp where myapp is the name of your module.
The example given is npm install --build-from-source=myapp, and the README explains the three situations where that is useful. The first is when myapp is referenced in the package.json of a larger app, and therefore myapp is being installed as a dependency with npm install. The second is when the larger app also depends on other modules installed with node-pre-gyp. The third is when you only want to trigger a source compile for myapp and not for the other modules.
That third case is the one that saves real time. Without the module name, --build-from-source forces every native dependency in the tree to compile from source, which on a large application is minutes of work for every install. With the name, only the one package you are debugging recompiles.
The --update-binary option is the inverse case, reinstalling by replacing a previously installed local binary with the remote one, which is what you want after you publish a new artefact and want to test it without a clean rebuild.
The other runtime-relevant option is --target, and the semantic difference between the source and fallback flags is subtle but real. --build-from-source means always compile, never download. --fallback-to-build means try the binary first and compile only if there is no matching one. The distinction matters when a binary is broken for a particular platform, because a fallback still tries it first.
The v1 to v2 move was a scope change, not just a version bump
The versioning carries real information, and it is spelled out in the README.
On February 9th 2021, @mapbox/[email protected] was released. Older, unscoped versions that are not part of the @mapbox org are deprecated, and only @mapbox/node-pre-gyp will see updates going forward. The upgrade path is shown as two commands:
npm uninstall node-pre-gyp --save
npm install @mapbox/node-pre-gyp --saveThe Node.js support matrix is the other half. The project will attempt to track the Node.js release schedule and will regularly retire support for versions that have reached EOL. The v2 line requires Node.js 18 or above and is marked as unreleased in the README, and the v1 line covered Node.js 8 and above.
The package.json confirms the current floor with an engines field of node >=18, and the current version is 2.0.4-pre.0.
The release tags show a v2 line in progress. The recent versions are v2.0.4-pre.0 on 2025-12-19, v2.0.3 on 2025-11-26 and v2.0.2 on 2025-11-26, and the last push to the repository was on 2026-10-19 with the repository not archived.
The 2.0 series is a pre-release line at the time of writing, and that matters for anyone pinning. The versioning also explains the package rename, and it is not a cosmetic change, since the module name is what your package.json install script invokes and what the scoped import path is.
The licence is BSD-3-Clause, with the LICENSE file in the repository as the authoritative text, and this is a licensing statement rather than legal advice.
The dependency list shows a tool that downloads rather than builds
The runtime dependencies tell you the design constraint that matters most for this tool.
There is consola for output, detect-libc for working out the libc on the target platform, https-proxy-agent for honouring a proxy when downloading, node-fetch for the download itself, nopt for option parsing, semver for version comparison, and tar for unpacking the downloaded archive.
Two of those are worth a second look. detect-libc is there because a prebuilt binary is not just about platform and architecture, it is about the C library. A binary built against glibc will not run on a musl system, and a project that publishes Linux binaries has to know which flavour it is targeting. And https-proxy-agent means the download path goes through a corporate proxy when one is configured, which is a requirement for anyone installing behind a firewall.
Notably absent is the AWS SDK. The README says the AWS SDK is a devDependency because install only uses http to fetch binaries, so the published package pulls a prebuilt artefact over plain HTTP and does not need a cloud SDK at all.
The devDependencies show the testing approach. There is mock-aws-s3 and nock for stubbing the S3 API and HTTP, tape as the test runner, nyc for coverage with an all flag and skip-full set to false, tar-fs for filesystem fixtures, node-addon-api for building a test addon, eslint 10 with the stylistic plugin and the n plugin, and @mapbox/cloudfriend for deploying the S3 bucket. The scripts include a bucket target running scripts/set-bucket.js, which is the infrastructure side of publishing.
The CI workflows are visible in the badges too: a general ci workflow and a separate s3-bucket workflow, which is the one that exercises the real hosting path rather than the mock.
Editorial conclusion
Adopt node-pre-gyp if you maintain a Node.js native addon and want most users to install a prebuilt binary instead of compiling, and you can run an S3 bucket or equivalent host for the artefacts. Do not adopt it if your addon is not native, since the whole tool is about compiled .node modules. Before you set it up, read the v2 requirements, because node-pre-gyp 2 targets Node.js 18 and above while the 1.x line was the one for Node 8, and decide whether to use --fallback-to-build so a user without a matching binary is not left with a broken install.
Frequently asked questions
What does @mapbox/node-pre-gyp do?
It stands between npm and node-gyp and offers a cross-platform method of binary deployment for Node.js C++ addons. It provides a node-pre-gyp command line tool that installs a package's C++ module from a binary, developer commands for packaging, testing and publishing, and a JavaScript module that can dynamically require the installed binary.
How do I configure my addon to use node-pre-gyp?
Add @mapbox/node-pre-gyp to dependencies, @aws-sdk/client-s3 to devDependencies, an install script of node-pre-gyp install --fallback-to-build, and a binary object in package.json describing module_name, module_path and the host URL the binaries are served from.
What is the difference between --build-from-source and --fallback-to-build?
Both can be passed alone or with a value, and you can pass --fallback-to-build=false to override the package.json setting. Passing --build-from-source=myapp triggers a source compile for that one module only, which is useful when a larger app depends on several node-pre-gyp modules and you only want to rebuild one.
Which Node.js versions does node-pre-gyp 2 support?
The v2 line requires Node.js 18 or above, while the v1 line covered Node.js 8 and above. The project says it will attempt to track the Node.js release schedule and regularly retire support for versions that have reached EOL, and the current version is 2.0.4-pre.0.
How do I migrate from the old unscoped node-pre-gyp package?
The README says the older, unscoped versions that are not part of the @mapbox org are deprecated and that only @mapbox/node-pre-gyp will see updates. To upgrade, run npm uninstall node-pre-gyp --save and then npm install @mapbox/node-pre-gyp --save.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mapbox-node-pre-gyp)Was this useful?