-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
esm: unflag import.meta.resolve #33464
Conversation
I'm concerned about cc @nodejs/modules-active-members |
@ljharb it is not importable because the difference between |
Other than that though, the resolvers are equivalent. |
Other useful use cases for this include resolving |
I think that if it's useful to be able to resolve non-importable paths (ie is, in both CJS and ESM, it's just not possible right now in CJS), then we need to pursue an API for both CJS and ESM to do so. The point of |
this was originally flagged because we wanted to work with the web to have some isomorphism here, is that still a goal? |
@ljharb the benefit of a singular API is static analyzability - I say this having done a lot of these types of analyses in node-file-trace and ncc for Vercel. ESM is more statically analyzable than CJS - we didn't have to restrict ourselves in the development of ESM to making it match CommonJS in terms of analyzability. You seem to be applying the same sort of argument in disallowing features which improve analyzability. I am not against a Ideally we can avoid seeing problems as mutually exclusive and appreciate that there are different benefits to different approaches. I don't think we should restrict the |
@devsnek if we wait for the web we will grow old in the mean time, and ship ESM without full features. |
@guybedford i'm not opposed to the ESM version of it being chained off of |
The resolver's job is to turn a specifier and a referrer into an absolute url. knowing whether that url can actually be loaded is separate, and requires a full import lifecycle. |
@devsnek while i don’t think that’s true in node, where all importable URLs are synchronously resolvable, the ESM API should then be async. The entire point of a resolve api is so you can load the result. |
no the point is to pass the resolved url to the source loader, which is the only part of node that understands whether or not the url can be loaded |
I agree with @devsnek here. It's already not fully true that a string generated from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the description, it looks like one of two things are true:
- Resolving
pkg/
doesn't honor./
inexports
, e.g. for people who want to do things like{"./": "./lib/"}
. - This isn't a reliable way to get the root
package.json
because it may accidentally resolve to./lib/packag.json
.
I'm still in support of unflagging this but I currently assume that (2) is the case. I would have concerns if this is (1).
In the absence of loaders (the default and common case), and assuming disk operations succeed (also the common case), require.resolve is requireable, and i expect (and i maintain, the common expectation will be) import.meta.resolve to be importable. |
That assumes the HTTP-based imports will never be a common thing. To me that's too big a bet to enshrine in our APIs. Especially given that it absolutely is a common thing in browsers and browsers are by far the most popular JS [module] runtime. I'm not saying I'm 100% sure that they will become common, just that I wouldn't want to design our APIs based on the assumption that they won't. |
I don’t think it will ever be a good idea nor a possible thing, but that still doesn’t mean this api should ever resolve a path that is known to be impossible to import. |
@ljharb it sounds like you're asking that the default resolver fail if it knows the resolved url won't be loadable? |
@devsnek yes, just like |
@ljharb that's not a change that would be made to |
@devsnek ok - why would the default ESM resolver allow (also, the point of |
@ljharb |
Has there been any signal from upstream that a standardized version of this is ready to land in browsers? I'm uncomfortable unflagging this until that point. While we do have TLA, it is still behind a flag... this to me seems premature |
I believe the closes thing is Compartments have a resolve hook. It does not currently allow you to reflect on your current context, but that was talked about in the last 2 meetings as a potential fix for a problem with polyfills. |
Given that |
As just discussed in the modules meeting, there was resistance to implementing this without having exact implementation equality with |
I think there is consensus that we can ship an equivalent: import { resolveURL } from 'module'; // <---- this
import { promises as fs } from 'fs';
const pkgUrl = await resolveURL(import.meta, 'pkg/');
const pjson = await fs.readFile(new URL('package.json', pkgUrl)); And potentially add it to |
Now that TLA has landed, the workflows around this are really quite nice.
For example, to load the package.json file from an external package one can write:
Note: this is in no way meant to be a full solution to the other issue discussion, where @ljharb has suggested some directions forward.
Other examples were included in the original PR - #31032.
I do think unflagging is important as this is a critical feature for ESM to ensure it has the
require.resolve
use cases supported.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes