-
Notifications
You must be signed in to change notification settings - Fork 188
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: package.exports array target not conforming to the ESM specification #400
Comments
Yeah... I think we need to do the same because other bundlers do it and we should not allow people make such mistakes, I am afraid it can be a breaking changes in some way, but in this case I want to say it is a bug fix. Do you want to send a PR? |
I can give it a try next week. Let's also wait for a response from the TypeScript team. |
@Boshen Yeah, let's wait, but I am still thinking it is a strange behaviour and should work as a fallback 😄 |
I’m very supportive of trying to make Has anyone checked Bun’s runtime behavior? |
@andrewbranch will Typescript align this behavior with Node.js (when moduleResolution se to |
@andrewbranch I check bun's behavior, it seems Bun even doesn't do fallback for |
@alexander-akait I have a same feeling, fallback for bad-specifier but not for non-exist file is really strange and the performance reason is only theoretical, fallback for non-exist file do help simplify monorepo configuration and it seems fallback for bad-specifier even less useful than fallback for non-exist |
I don't think I can patch these two ESM problems (this issue and #399). The current implementation is not following the ESM specification, resulting conflicting behaviors or major breaking changes that I don't know how to make decisions nor how to make the correct changes. For example, the code for checking export target enhanced-resolve/lib/util/entrypoints.js Lines 198 to 227 in 58464fc
is different from
resolver.doResolve(
target,
obj,
"using exports field: " + p,
resolveContext,
- callback,
+ (err, result) => {
+ if (result === undefined && /* target is not "Invalid Package Target" */) {
+ callback(new Error(`Cannot find module ${obj.path}`));
+ } else {
+ callback(err, result);
+ }
+ }
); I think the best way forward is to update the documentation around https://webpack.js.org/guides/package-exports/#alternatives, either remove it, or change it to the "fallback to typescript" use case "exports": {
".": {
"development": "./src/index.ts",
"default": "./dist/index.js"
},
"./types": {
"development": "./src/types.ts",
"default": "./dist/types.js"
}
} |
@Boshen Sorry for delay, I think we should be align to the spec, but, yes, some developers can rely on our logic, that is why I think we can intoduce the new options to return the old behaviour and will write this in changelog, so it will allow to migrate smoothly. Yes, such changes are sometimes painful, but non-standard opportunities are even worse. |
If we encounter this very often, then we may revert to the old behavior and use |
Repro and research: https://github.com/Boshen/test-esm-exports-array
Pasting the content here:
Resolving package.exports array target
Background
ESM can define an array as the exports target:
Given only
./existent.js
is on disk,enhanced-resolved
will resolve to./existent.js
while Node.js will throw a "./non-existent.js
not found" error.Explanation
The ESM specification states the following:
Notice the last line
continuing the loop on any Invalid Package Target error.
."Invalid Package Target Error" does not mean "File not Found".
This means the above package.json should yield
./non-existent.js
instead of./existent.js
.The reason for this is that
exports
is designed to resolve unambiguously without hitting the disk.Also documented by here:
enhanced-resolved
As documented on the Webpack website:
At the moment of writing, I have yet to find a legitimate use case for this feature,
but the behavior from Webpack will lead to people setting up their exports array for some use cases that can break future compatibility.
We have already seen this with the browser field.
All build tools has been reported with the same problem with the same discussions over and over again, linking to the issues:
moduleResolution: bundler
, does not conform to the spec according to the implementationReproduce
Notice
enhanced-resolve
resolved to./existent.js
, spec compliant implementations reports./non-existent.js
not found.The text was updated successfully, but these errors were encountered: