Repository navigation
Conversation
… of the context Webpack and Rspack resolve symlinks in module paths (`resolve.symlinks` is on by default). The virtual module prefix was built on `compiler.options.context` as given, so when the context goes through a link (any project under macOS's `/var`, or a linked project folder) the virtual module was written under the link, the resolver followed the link to the real path, and the build failed with ENOENT on `<real>/_virtual_...` (webpack) or `<real>/node_modules/.virtual/...` (rspack). The prefix is now built on the real path of the context, which is also what the loaders and the importer decoding compare resolved paths against. A context that does not exist keeps the path as given.
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
resolves #640
Description
When the
contextof a webpack or rspack build goes through a symlink, every virtual module fails to build with ENOENT. The reproduction is in #640.Cause. The virtual module prefix is built on
compiler.options.contextas given. The virtual module is written under that path, but both resolvers follow symlinks (resolve.symlinksis on by default), so the module is then read from the real path, where nothing was written. The loaders and the importer decoding also compare the resolved (real) path against the prefix.Fix. Build the prefix on the real path of the context in both adapters, through a small
realContexthelper insrc/utils/webpack-like.ts.realpathSyncand notrealpathSync.native: it resolves only links and junctions, and leaves Windows short names (RUNNER~1) and letter case as the context gave them. This matters on Windows: when rspack resolves through a link it also expands short names, while webpack keeps them, so the safe prefix is one with no link left to resolve.resolve.symlinks: falsenothing changes in practice: the virtual path is built on a path with no links in it, so it resolves to itself.Tests
test/unit-tests/symlinked-context: webpack and rspack builds whose context is a symlink to the project (a junction on Windows), with one virtual module importing another. The test checks four things:loadreceives both ids;resolveIddecoded;loadreturned.On
mainit fails with the ENOENT errors from webpack/rspack: virtual modules fail with ENOENT when the build context goes through a symlink #640. With the fix it passes. Reverting only one adapter's change fails only that bundler's case.A direct test of
realContextintest/unit-tests/utils/webpack-like.test.ts.pnpm test,pnpm lintandpnpm typecheckpass locally (Linux, Node 22).The repo's CI, run on my fork:
/varlink on macOS), and the rest of the suite passes. (run)Notes
src/webpack/index.tsandsrc/rspack/index.ts, so whichever lands second needs a one-line rebase. I merged the two locally, kept both imports, and the tests of both pass.resolveIdwith a leading separator (/\0virtual-a), with or without a symlink, because the importer is sliced at a prefix that has no trailing separator. The new test tolerates that. I can send a separate fix if you want one.Summary by CodeRabbit