rules_js 3.0 - out with the old (and default to the new)

rules_js 3.0 is now available. This release simplifies the internals by dropping support for older Bazel, pnpm, and Node versions while keeping the public rules_js APIs stable, prioritizing maintainability, performance, and correctness over new surface features.
We've also launched new documentation with this release, at https://docs.aspect.build/bazel/javascript
If you're already on Bazel 7+, loading rules_js via MODULE.bazel, and using pnpm 9+, the upgrade should be straightforward.
What’s Changed?
🚫 Remove Bazel 6 support
🚫 Remove pnpm 8 support
🚫 Remove WORKSPACE support
🧹 Remove some rarely used APIs
✅ Enable enhancements that were previously opt-in
Ecosystem Compatibility
Related rulesets including rules_ts, rules_swc, rules_jest, and rules_webpack have been tested with rules_js 3.0 and are compatible with their current releases.
The dependency on aspect_bazel_lib 2.x has been replaced with bazel_lib 3.0 (2567). With this change, rules_js ensures any aspect_bazel_lib usage remains forward-compatible with bazel_lib, as long as your repository does not override the aspect_bazel_lib module.
The most significant change is the removal of pnpm 8 and WORKSPACE support.
Early versions of rules_js were designed around:
The pnpm lockfile format at the time
Limitations of Bazel repository rules in WORKSPACE mode
To avoid diverging code paths:
When pnpm updated its lockfile format,
rules_jsdowngraded it internally.When Bazel MODULEs (bzlmod) were introduced,
rules_jsdelegated much of the logic back to WORKSPACE-based implementations.
That approach kept behavior consistent, but added complexity and limited adoption of newer pnpm and bzlmod features.
With pnpm 8 and WORKSPACE removed:
The core architecture is simpler
Legacy compatibility layers are gone
A single modern code path replaces multiple branches
Bugs such as the pnpm lockfile being parsed twice under bzlmod (2480) are eliminated
Notable CHANGELOG
📦 Platform-specific optional npm dependencies (2538)
That annoying @esbuild/android-arm64 you always see being fetched and know you really don't need will no longer be fetched. Other common examples are platform specific @swc/*, @rollup/* or the upcoming @typescript/native-preview-* packages.
🔗 proto_library support in JS deps (2721)
Experimental support for directly depending on proto_library targets in js_library(deps) or ts_project(deps). You register a protoc plugin toolchain for your choice of codegen tooling.
🗂 Package exclusion presets + default exclusion list (2652)
That 10mb CHANGELOG.md you always notice? Gone!
The npm_exclude_package_contents API now has multiple presets instead the previous single use_defaults = True which was opt-in. The previous use_defaults = True has been replaced with the "yarn_autoclean" preset which mimics the yarn autoclean command. A new "basic" preset is now available and enabled by default - this is less aggressive then the yarn list while still excluding common unnecessary files often shipped in npm packages.
⚡ Better Bazel 9 compatibility and performance
Bazel 9 has some new features such as the facts API which will now be used to make things like pnpm downloads reproducible even if you don't manually provide SHAs (2698).
Path-mapping support has also been expanded (2575).
🛣 Initial support for Bazel path mapping (2575)
Bazel path mapping allows some actions to be cached and reused across compilation modes such as dbg and release.
🟢 Default Node version bumped to v22 (2649)
Along with upgrading the minimum rules_nodejs version the default node version is now also updated to the LTS v22.
What's Next
rules_js 3.0 is launched and ready for you to upgrade. Check out the updated docs or try a new project using the https://github.com/bazel-starters/js repo which has all the latest versions.
Having problems? Aspect offers a paid support plan with a dedicated Slack channel for your team under an SLA.




