-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
import.meta.resolve implementation #7296
Comments
We shouldn't implement this unless browsers do. |
The model for The same model can apply to Browsers have no driving need to implement this, so if we (Node.js and Deno) wait, we may wait years. I'm happy to leave this open to track further though. |
This looks like something that can be fully implemented in userland with We don't have node resolution, so I guess the implementation would more or less look like this: It also does not really make sense for this to return a |
That method should probably take into account currently loaded import map, so it would actually be an op. |
Ah right - import maps... 🤦 |
Yep, |
TC39 doesn't deal with things like module resolution. @guybedford is there no interest in WhatWG that you are aware of? I know module loading and resolution is never a straightforward topic! 😉 |
(Also for the record, |
The benefit of If Node.js and Deno have their own custom functions and encourage that, those patterns get engrained in usage and users have code that does conditional checks and calls these different functions - the build tooling to deal with bundling while retaining asset references becomes very specific to each platform then or needs lots of custom work. The custom usage for a library then looks something like: function crossPlatformResolve (specifier) {
if (typeof Deno !== 'undefined') {
return Deno.resolve(specifier, import.meta.url);
} else if (typeof process !== 'undefined' && process.platform.node) {
// nodejs has yet to specify such a custom resolver too
return require('module').nodeResolve(specifier, import.meta.url);
} else {
// etc for all other platforms
throw new Error('no resolver found');
}
}
const template = await (await fetch(crossPlatformResolve('pkg/template.html')).text(); when it could just have been: const template = await (await fetch(import.meta.resolve('pkg/template.html')).text(); which systems like asset relocators can then statically replace with: const template = await (await fetch(import.meta.url + '../path-to-inlined-template.html')); as a pattern for bundling asset references. The alternative of custom function patterns without statically analyzable assets being easy becomes the path the longer we wait, and it's fine, but we can just do much better if we can move now. As mentioned, I feel that environments like Deno and Node.js have the driving use cases here, the browser doesn't necessarily. Waiting on WhatWG means giving up agency, as neither Deno nor Node.js have any voice at WhatWG. There was a WhatWG PR for this in whatwg/html#5572, the main contentions there were whether it should be sync or async, and whether there should be a second argument or not. To give you the gist of the current situation:
I understand completely (3) is the easy status quo though :) |
@guybedford I would vote against implementing a non-standard like that. |
@timreichen I didn't say this should be implemented in the |
@lucacasonato sorry read that wrong. Corrected. |
Re sync vs async, the permissions API would be a precedent for us going async to match the standard even though the underlying calls are sync. I don't see what reason anyone would have to ever "expect" a sync API without concerning themselves with the implementation. |
Well, we in theory want to be able to resolve async, especially for remote modules. This is where the semantics differ from Node.js in that would we return the initial URL for a module, or the final redirected URL for a module? All this being said, @bartlomieju and I are embarking on some major refactors of how we do dependency analysis determining what processing or not needs to be done to modules. It feels like this is something we might want to consider after the dust settles on that. |
Thanks for the feedback here, it does sound like those refactorings / resolver concerns in Deno need to be fleshed out more in order to determine what is best for Deno here further with regards to APIs here. It would be great to work towards alignment between Node.js and Deno when those directions are ready, and I will continue to reiterate that specifications are secondary to implementations, and in this space Node.js and Deno have the interest end engagement of the implementation / ecosystem conventions first and foremost. There is certainly risk diverging from browsers yes, but if we were to eg jointly propose such browser specs as part of the implementation / unflagging process I'm sure it would be well received. I'd be more than happy to collaborate on specification work here as well. |
I don't think there are any more blockers to this feature. Our internal infrastructure has synchronous APIs for resolving module specifiers so I'm not sure if we need to to be async. @kitsonk what's the use case for remote modules you mentioned in #7296 (comment) ? |
So Node has Again, from my point of view there are no blockers for this feature and we could implement it easily. @guybedford are there are signals from committees/browser vendors about interest in the API? |
@bartlomieju browsers are definitely interested, although I believe still for a sync version not an async version. What's your opinion on that matter? Node.js loaders are fully async but in theory could be syncified using separate processes. At a low level though resolve has always felt like an async operation when considering CDN lookups to me. But I'm open to changing my mind. |
I do tend to agree with you. Currently |
For a resolved module graph. Try to resolve something outside that module graph, then it would become async again. silly phone Unless we accept that the resolve simply "guesses" at what the target is, not accounting for redirects, etc. |
@kitsonk I thought this utility is just for resolving URLs? Unless there are some DNS lookups done this is purely computational utility? At least that is the signature that we have in built-in |
Yeah, but the module loader calls the module graph and the module graph has all the dependencies resolved including the import map. I will take a look at it deeper to see if we change our response based on what is on the graph, or if we wait until the load. I am just saying there is a risk that we might not have all the information to hand to give a definitive response. |
I see what you mean and that's okay. Anyway I'm in favor of API being asynchronous like it is in Node. |
@kitsonk Is that assuming It seems |
Discussing with @domenic further on this it does sound like it will be unlikely that Chromium would implement async here, and that a lot of the internal mechanics are built around sync resolve. Node.js will have a hard time going sync as it involves syncifying the loader pipeline, but it may be worth Deno reconsidering going sync here to try to aim for browser alignment. That would then mean treating any async resolution work or lazy import maps extensions as part of separate mechanisms that don't block resolve, and could have their own lifecycle events. |
Any of that would be on the Rust side, which we can always "op" sync if we need to, even if it is back by async operations, just means the event loop would be paused. We used to do it with embedded Currently, when you try to resolve/load something outside of the current statically analysable graph (like a non-analyzable dynamic import or a web worker script) you end up building another static dependency graph which gets loaded, checked and emitted before returning. |
Node.js has been shipping an
import.meta.resolve
implementation for some time behind the--experimental-import-meta-resolve
flag described briefly here - https://nodejs.org/dist/latest-v14.x/docs/api/esm.html#esm_no_require_resolve.In Deno such a function could resolve the local import map when set including applying scope resolution based on the current module context.
Is there interest from Deno in implementing this API? I don't think it would be sensible for Node.js to unflag this feature without getting wider support, but Deno is likely the only other environment that might benefit from this. Feedback would help us to consider the unflagging process.
The text was updated successfully, but these errors were encountered: