Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose file resolution as a utility #51855

Open
ef4 opened this issue Feb 23, 2024 · 13 comments
Open

Expose file resolution as a utility #51855

ef4 opened this issue Feb 23, 2024 · 13 comments
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. feature request Issues that request new features to be added to Node.js. loaders Issues and PRs related to ES module loaders loaders-agenda Issues and PRs to discuss during the meetings of the Loaders team

Comments

@ef4
Copy link

ef4 commented Feb 23, 2024

What is the problem this feature will solve?

Tool authors often need to reimplement Node's resolving behaviors in order to ask the question: if this file was to import this path, which file would Node resolve that to?

This comes up for build tools like Vite, Esbuild, or Webpack. It also comes up for analysis tools like Eslint and Typescript.

For a long time, people were able to get by with the likes of https://www.npmjs.com/package/resolve. But the introduction of the full suite of package.json exports features (conditions, subpath imports, etc) and ESM have resulted in a situation where almost no tool actually covers Node's complete spec correctly anymore. It seems wasteful to try to fix all these parallel implementations rather than share node's implementation as a utility.

What is the feature you are proposing to solve the problem?

A node-provided, importable constructor that takes conditions:

import { Resolver } from 'node:resolver';
let r = new Resolver({ 
  conditions: ['default', 'node', 'development' ]
});

Where the Resolver instance offers a method with the signature:

resolve(requestedPath: string, requestingFile: string): Promise<string | undefined>;

The key features provided here that are not provided (AFAIK) by any existing Node API are:

  • you can programmatically ask what would happen under the given conditions. These are distinct from the global --conditions that prevail in the current node process (remember -- we're talking about running this inside a tool like a linter. Regardless of what conditions the linter uses for its own implementation, it should follow imports the way the user's program is going to do it, using the user's conditions.)
  • you can ask on behalf of another file in another package. Critically, this would need to respect rules like self-referencing. This is in contrast with require.resolve which, even if you set paths to the inside a package doesn't respect the self-referencing rule.

Note that I'm definitely not asking for access to the state of the current node process's resolver. I don't want its customized loaders, I don't want to share its cache. Rather, this would be asking to set up an entirely separate state that would not interfere with Node's own module loading at all.

What alternatives have you considered?

There are lots of third-party implementations, maintained at great effort and all with incomplete support for Node's behaviors. In theory somebody could invest the effort to make one of them perfect and continually invest in making it follow new node features.

@ef4 ef4 added the feature request Issues that request new features to be added to Node.js. label Feb 23, 2024
@avivkeller avivkeller added esm Issues and PRs related to the ECMAScript Modules implementation. loaders Issues and PRs related to ES module loaders labels May 5, 2024
@avivkeller
Copy link
Member

avivkeller commented May 5, 2024

IIUC, you mean a similar function to require.resolve, where the user can supply conditions (maybe also runtime keys)

Said function would be used like:

resolve("my_module", { conditions: ["default"], entryPoint: "..." })

Am I understanding correctly?

@ef4
Copy link
Author

ef4 commented May 5, 2024

Yes, assuming that your example's "entrypoint" means "resolve from the perspective of this file".

@avivkeller
Copy link
Member

@nodejs/loaders Hypothetically, could the Modules cache contain references to each import path condition so that the resolution could hop around the different conditions?

@GeoffreyBooth
Copy link
Member

We shouldn't cache what we don't use. For the purposes of this API the cache can be checked first but if it doesn't have what we need then we read from disk again. We shouldn't slow down the default case for someone potentially using this utility API.

@avivkeller
Copy link
Member

Okay, thanks.

I was just wondering because if the default condition is cached, but the user is trying to get a different condition, this API (if it checks the cache) could return the wrong value.

Copy link
Contributor

github-actions bot commented Nov 2, 2024

There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-stale Mark issue so that it is never considered stale label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot added the stale label Nov 2, 2024
@mansona
Copy link

mansona commented Nov 3, 2024

This issue is very much still relevant 🤔 Is this comment enough to remove the stale label?

@github-actions github-actions bot removed the stale label Nov 4, 2024
@JakobJingleheimer
Copy link
Member

Is this not import.meta.resolve(specifier)? And if you need to do it relative to a different module than the current, import.meta.resolve(specifier, relativeTo) (requires --experimental-import-meta-resolve).

@ef4
Copy link
Author

ef4 commented Nov 5, 2024

No, that is not the same thing. It doesn't let you choose the import conditions.

@JakobJingleheimer
Copy link
Member

JakobJingleheimer commented Nov 5, 2024

It doesn't let you choose the import conditions.

Perhaps it could. The 2nd argument is already node-specific and conditions are very relevant to what it's doing, so I could see providing a 3rd config object argument.

@cseas
Copy link

cseas commented Nov 6, 2024

@sosoba
Copy link
Contributor

sosoba commented Dec 2, 2024

I create pull request for it lukeed/resolve.exports#37

@JakobJingleheimer JakobJingleheimer added the loaders-agenda Issues and PRs to discuss during the meetings of the Loaders team label Dec 2, 2024
@romainmenke
Copy link

This would also help us for our CSS bundler for those CSS authors who want to import a stylesheet from an npm package or other module.

Currently we use require.resolve, but this doesn't allow us to specify style as an import condition. (Not that style is standardized at this time.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. feature request Issues that request new features to be added to Node.js. loaders Issues and PRs related to ES module loaders loaders-agenda Issues and PRs to discuss during the meetings of the Loaders team
Projects
Status: Awaiting Triage
Development

No branches or pull requests

8 participants