rules_nodejs keeps the Node toolchain and drops the Node rules
NodeJS toolchain for Bazel.
At a glance
- What is it?
- rules_nodejs gives Bazel a Node.js toolchain and runtime, and since the 6.x branch it deliberately no longer ships the rules for using Node.js such as nodejs_binary, pointing users at rules_js instead. It is maintained by volunteers in the Bazel community rather than by Google.
- Who is it for?
- rules_nodejs is the right dependency for a Bazel repository that needs a pinned Node.js toolchain and runtime for an existing rules set, and it is a reasonable one to adopt for its support matrix and its role in vetting new Bazel releases. It is the wrong dependency for a project expecting nodejs_binary or the other Node rules, because the 6.x branch removed them and the README points to rules_js for that work.
- Can I use it commercially?
- Yes. Apache-2.0 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 last received commits 1 day ago.
- What is it written in?
- Mainly Starlark, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A toolchain without the rules that use it
The first thing to understand about rules_nodejs is what it is not. The README states plainly that the ruleset provides a Node.js development toolchain and runtime with Bazel, and that it does not have any rules for using Node.js, such as nodejs_binary. For that, the project recommends rules_js, hosted under the aspect-build organisation. So the package is a toolchain definition, the thing that says which Node.js version to download and how to expose it to a build, without the rule layer that would let you declare a Node binary, run a test or bundle a package. That split is a deliberate 6.0 decision rather than an accident, and it has a practical consequence for anyone arriving with an existing Bazel setup: the toolchain and the rules come from two different repositories that have to be versioned against each other.
The 6.x branch is a scope reduction, not a feature release
There is a section in the README titled 6.0 Scope Reduction, and it deserves close reading. The 6.x branch is the latest release line, and the README says it has a greatly reduced scope from previous releases because most of the code was unmaintained. The 5.x branch is where the prior state of the repository lives. Read plainly, that is a project that removed code it could not keep working rather than a project that added capability. It is an unusual thing for a release note to say, and it has direct consequences. Anyone who upgrades a 5.x based setup to 6.x will find rules missing, and the missing rules have a named replacement in a different repository, so the migration is a dependency change rather than a rename. The three most recent tagged releases, v6.7.6 on 2026-09-03, v6.7.5 on 2026-06-24 and v6.7.4 on 2026-04-03, all sit inside that reduced 6.x line, which tells you the project is still iterating on what remains.
Support matrix and versioning live in /index.bzl
The README explains the release contract with unusual clarity. The project follows semantic versioning, where patch releases carry bugfixes and minor releases carry new features, and only major releases such as 1.x and 2.x are allowed to have breaking changes. That guarantee is what makes a toolchain dependency safe to hold at a pinned version. For Bazel itself, the project supports LTS releases starting at 4.x, and it points at a file called SUPPORTED_BAZEL_VERSIONS inside /index.bzl as the authoritative list of versions tested against. That is the file to read before you adopt, because it tells you exactly which Bazel releases are covered rather than leaving you to infer support from release tags. The README also notes that the repository is maintained by volunteers in the Bazel community and that neither Google nor the Bazel team provides support for the code, while the same paragraph points out that the repository is part of the test suite used to vet new Bazel releases.
The repository is a Bazel module with a pinned Node version
The layout at the root tells you how the module is assembled. MODULE.bazel marks the repository as a Bazel module, .bazelversion pins the Bazel version the project itself builds against, and .bazelrc and .npmrc hold the shell and npm configuration. The nodejs/ directory carries the toolchain rules and the generated version table, packages/ holds the published npm packages, internal/ and external/ hold implementation and vendored third-party code, and e2e/ holds end-to-end tests. The .aspect/ directory, the .bcr/ directory and the .bazelci/ directory show that the project is set up for the wider Bazel ecosystem tooling, and the homepage in the repository metadata points at the Bazel registry documentation for the module. The package.json at the root describes the repository itself rather than a published artefact: it is marked private, the version is 0.0.0, and it declares the toolchain constraints that matter to an adopter.
Node version constraints and the pnpm pin in package.json
The root package.json is worth reading before you depend on this repository, because it states the environment the project expects. Two fields matter most for an adopter. The engines field constrains the Node.js version the repository's own tooling runs on, and the packageManager field pins the package manager. Here they are as written:
"engines": {
"node": ">=12 <20"
},
"packageManager": "[email protected]",
"devDependencies": {The engines range stops at Node 20, and the package manager is pinned to pnpm 8.11.0, which is consistent with the pnpm-lock.yaml file at the root of the repository. The devDependencies are the developer-side tooling: bazelisk for running the right Bazel version, buildifier and buildozer for working with BUILD files, commitlint and conventional-changelog-cli for the changelog, and a pre-commit config file and a prettier ignore file at the root alongside it. The scripts section of the same file describes how the Node version table is regenerated.
The Node version table is generated, not hand written
The second script in package.json is the more interesting one for anyone tracking the toolchain, because it points at a file inside the toolchain rules that is generated rather than committed by hand. The update-nodejs-versions script runs a Node script from the scripts/ directory and redirects its output into nodejs/private/node_versions.bzl:
"update-nodejs-versions": "node ./scripts/update-nodejs-versions.js > nodejs/private/node_versions.bzl",The private naming convention on that path marks the file as internal to its package, and the fact that the file is produced by a script means the set of Node versions the toolchain can select is data you can inspect and regenerate rather than something buried in rule logic. The other script updates the changelog from conventional commits, which explains the commitlint config and the conventional-changelog configuration in the same file. If you are pinning this repository, the node_versions.bzl file is the one to read to see which Node versions are actually on offer.
Where this project stops being the right answer
The clearest wrong-tool case is a team that wants nodejs_binary and expects to find it here. The README states the rules are absent and points at rules_js, so the honest answer is that rules_nodejs alone will not give you a Node binary rule. The second wrong-tool case is a repository that cannot accept volunteer maintenance. The project says in plain words that it is maintained by volunteers in the Bazel community, that Google and the Bazel team do not support the code, and that most of the code was unmaintained in the previous release line, which is why the scope was cut. The third is a team that wants a specific Node.js version outside the generated table. Nothing in the documentation describes how to add a Node version that is not in node_versions.bzl, so extending the toolchain means reading the update script and running it yourself. There is also no getting-started command in the README, only a pointer to the docs/ folder and to the generated API documentation on the Bazel registry, so the setup path is documentation you have to read rather than a single command to run.
Editorial conclusion
rules_nodejs is the right dependency for a Bazel repository that needs a pinned Node.js toolchain and runtime for an existing rules set, and it is a reasonable one to adopt for its support matrix and its role in vetting new Bazel releases. It is the wrong dependency for a project expecting nodejs_binary or the other Node rules, because the 6.x branch removed them and the README points to rules_js for that work. Before adopting, read the SUPPORTED_BAZEL_VERSIONS list in /index.bzl to see which Bazel releases are tested, check the node range your build needs against the >=12 <20 constraint in package.json, and note that the last push to the repository was recent, on 2026-10-21 with the 5.x branch holding the older, wider scope.
Frequently asked questions
What does rules_nodejs provide and what does it not provide?
It provides a Node.js development toolchain and runtime for Bazel. It does not provide rules for using Node.js such as nodejs_binary, and the README recommends rules_js from aspect-build for that.
Which Bazel versions does rules_nodejs support?
The project supports Bazel LTS releases starting at 4.x. The authoritative list of tested versions is in the SUPPORTED_BAZEL_VERSIONS entry inside /index.bzl.
What changed in the 6.0 release of rules_nodejs?
The 6.x branch has a greatly reduced scope from earlier releases because most of the code was unmaintained, according to the README. The 5.x branch holds the prior state of the repository.
Who maintains rules_nodejs?
It is maintained by volunteers in the Bazel community. The README states that neither Google nor the Bazel team provides support for the code, while noting that the repository is part of the test suite used to vet new Bazel releases.
How is the list of Node.js versions in rules_nodejs kept up to date?
A script in the root package.json runs node ./scripts/update-nodejs-versions.js and writes its output to nodejs/private/node_versions.bzl. The repository also pins pnpm 8.11.0 through the packageManager field and requires Node >=12 <20 through the engines field.
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/bazel-contrib-rules-nodejs)Was this useful?