You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[node-resolve] Replace resolve and some rollup-baked exports fields handling with a Rust-based resolver #1874
Currently, @rollup/plugin-node-resolve relies on resolve, a resolver created and maintained by Browserify, which hasn't been actively maintained and lacks the export map feature.
Rollup builds @rollup/plugin-node-resolve on top of resolve with extra code to handle the browser field and export map.
The resolve plugin is a hot path during the build process, ranging from 10 to thousands or even more. Rustifying the resolver could benefit performance.
Feature Proposal
Maybe Rollup could rustify the resolve part, starting with @rollup/plugin-node-resolve. It is possible to use a Rust-based resolver, like oxc-resolver or rspack-resolver directly. Rollup could also build a rollup-flavored one on top of those crates.
Also, those resolvers already support features (that resolve doesn't have) like export map and the browser field, so @rollup/plugin-node-resolve wouldn't need to re-implement those features again.
After experimenting with @rollup/plugin-node-resolve, we could then decide whether the Rollup core's built-in resolver can benefit from rustify as well.
I am not sure if it definitely needs to be "Rust" to improve performance, but I agree that completely owning the resolver will bring benefits. The greatest benefits I actually see from caching all directory accesses etc. during each build, something that currently is only done in the part handled by the old resolve plugin but not by the new parts.
But sure, it can also be Rust as long as jump between JavaScript and Rust does not become another bottleneck.
Unfortunately, I had little resources to pursue anything here, but I would be open if someone else picked it up.
unrs-resolver doesn't support options of @rollup/plugin-node-resolver, and supporting those options will affect performance. So the Jest case doesn't make any points here.
is-core-module (can be replaced with native isBuiltin)
hasown (replaceable with Object.hasOwn)
function-bind (replaceable with function.prototype.bind)
path-parse (replaceable with path.parse)
supports-preserve-symlinks-flag
One maintainer (ljharb) maintains all of these except path-parse, and has demonstrated an unwillingness to clean up dependencies despite native replacements existing, claiming security*. resolve uses about 50 TB of bandwidth weekly.
* In an issue on is-core-module:
Technically it’s Object.prototype.hasOwnProperty.call, and that relies on both Object.prototype and Function.prototype being unmodified.
Using hasown ensures that later mutation of builtins doesn’t break things, so it’ll be relevant and necessary and beneficial forever.
Mutation can occur before importing this one
This is not the job of the package, this is the responsibility of the JS host (shout out to --frozen-intrinsics)
const hasOwn = Object.hasOwn is a one line replacement for the 41.8 kB from hasown + its dependencies
There is zero need to polyfill function.prototype.bind, it has existed on every JS host for the past 15 years
@james-pre ljharb polyfill issue is not a concern here. My concern is that, currently rollup/plugin-node-resolve implements its own exports map resolution, where we may use other battle-tested resolving libraries, like enhanced-resolve or oxc-resolve to avoid re-inventing wheels.
Activity
lukastaegert commentedon Jun 1, 2025
I am not sure if it definitely needs to be "Rust" to improve performance, but I agree that completely owning the resolver will bring benefits. The greatest benefits I actually see from caching all directory accesses etc. during each build, something that currently is only done in the part handled by the old
resolveplugin but not by the new parts.But sure, it can also be Rust as long as jump between JavaScript and Rust does not become another bottleneck.
Unfortunately, I had little resources to pursue anything here, but I would be open if someone else picked it up.
SukkaW commentedon Jun 1, 2025
I see benefits from native
exportsandbrowserfeatures, which are currently still maintained by rollup (which only adds burdens).webpack's
enhanced-resolvecould be the JavaScript alternative and is battle-tested. Also supportsexportsandbrowserby default.JounQin commentedon Jun 10, 2025
@lukastaegert Just FYI,
resolvehas been replaced by https://github.com/unrs/unrs-resolver#readme in Jest 30: https://jestjs.io/blog#performance--memory-improvementsSukkaW commentedon Jun 10, 2025
unrs-resolverdoesn't support options of@rollup/plugin-node-resolver, and supporting those options will affect performance. So the Jest case doesn't make any points here.JounQin commentedon Jun 10, 2025
Then
oxc-resolverand@rspack/resolverare even worse, LOL.james-pre commentedon Jul 2, 2026
Why not use
import.meta.resolve?SukkaW commentedon Jul 2, 2026
Because to avoid breaking changes,
rollup/plugin-node-resolvestill needs to support the CommonJS resolve algorithm.james-pre commentedon Jul 3, 2026
I took a look at all of
resolve's dependencies:isBuiltin)Object.hasOwn)function.prototype.bind)path.parse)One maintainer (ljharb) maintains all of these except path-parse, and has demonstrated an unwillingness to clean up dependencies despite native replacements existing, claiming security*.
resolveuses about 50 TB of bandwidth weekly.* In an issue on is-core-module:
--frozen-intrinsics)const hasOwn = Object.hasOwnis a one line replacement for the 41.8 kB from hasown + its dependenciesfunction.prototype.bind, it has existed on every JS host for the past 15 yearsSukkaW commentedon Jul 3, 2026
@james-pre ljharb polyfill issue is not a concern here. My concern is that, currently
rollup/plugin-node-resolveimplements its own exports map resolution, where we may use other battle-tested resolving libraries, likeenhanced-resolveoroxc-resolveto avoid re-inventing wheels.