Open Boshen opened 6 months ago
Sounds like a bug, we need to fix it, thank you for issue, if you have time - PR welcome
@alexander-akait
For both test case (ESM array fallback and this one), it seems like we just need to abort the resolution in the exports field plugin.
But I tried for like an hour but still can't figure out the correct combination of callback()
calls to abort the algorithm in the two callbacks here:
Maybe it's easier for you to add the relevant code :-(
As for test cases, array fallback:
A new test is needed for this issue.
@Boshen We just need to do this https://github.com/webpack/enhanced-resolve/blob/main/lib/ExportsFieldPlugin.js#L74, maybe adding link why it happens will be great, so developers will less ask why it was changed
Repro and summary - https://github.com/Boshen/test-nested-exports
Pasting the contents here:
Resolving to the incorrect package with webpack (enhanced-resolve)
tldr;
In a monorepo, ESM saves us from resolving to the wrong package when package exports is configured, webpack (enhanced-resolve) fails to do so.
Scenario
In a monorepo, there are two versions of the same
package
installed in the root (node_modules/package
) and in a workspace directory (packages/app/node_modules/package
).node_modules/package
The root
node_modules
, withpackage.json
andindex.js
:node_modules/package/src/index.js
node_modules/package/package.json
packages/app/node_modules/package
And in a app
node_modules
, withpackage.json
andmain.js
packages/app/node_modules/package/src/main.js
packages/app/node_modules/package/package.json
Notice this one does not contain index.js.
Behavior
resolve('/path/to/packages/app', 'package/src/index.js')
enhanced-resolve
The incorrect behavior that comes from enhanced-resolve:
When resolving the specifier
package/src/index.js
inside./packages/app
, it first resolves the specifier to./packages/app/node_modules/package/src/index.js
and misses the file. It then continues searching and finds./node_modules/package/src/index.js
.node.js
The correct behavior from Node is:
Aborts when
./packages/app/node_modules/package/src/index.js
is not found.Explanation
Follow the spec (https://nodejs.org/api/modules.html#all-together)
The route
LOAD_NODE_MODULES
->LOAD_PACKAGE_EXPORTS
->RESOLVE_ESM_MATCH
->THROW "not found"
indicates that resolution should stop when a path is not found package#exports.
As a bonus point, the scenario will resolve to the root
./node_modules/package/src/index.js
ifpackage#exports
are removed from bothpackage.json
s.Replicate
To replicate the behavior, run
bash test.sh
and see the following output:esbuild
esbuild conforms to the spec.
Add
import 'package/src/index.js'
to./packages/app/index.js
Remove both
package#exports
and notice it resolves to the root package: