Environment
unplugin: latest (also present on current main)
webpack: 5
Also seen with Next.js webpack (next dev) when the filesystem cache is enabled
Reproduction
On current main, this unit test fails with ENOENT on _virtual_~demo:
pnpm exec vitest run test/unit-tests/webpack/virtual-cache.test.ts
The case that fails fakes a skipped resolveId (a resolver already returns the _virtual_ path). That is the same skip webpack does when it restores the path from its on-disk cache.
A PR with that test and a fix is at #617.
The on-disk cache path was reproduced by starting and stopping a Next.js webpack app with the filesystem cache enabled. After a restart, compile fails with ENOENT on _virtual_… until the placeholder is created again.
Describe the bug
On webpack, unplugin serves modules that are not real files by creating an empty placeholder in memory during resolveId and pointing the module at a made-up _virtual_ path. The plugin's load hook supplies the real source.
Webpack then stores that _virtual_ path in its on-disk cache. The placeholder never reaches disk, so a new process starts without it.
When the cache is reused, webpack already knows the path and skips resolveId. It then opens the path and fails with ENOENT.
This shows up after a next dev restart, or a CI or Vercel build that reuses .next/cache.
I have a PR for this: #617.
Additional context
Downstream report: unplugin/unplugin-icons#206
Same family as #32 (that issue used the older virtual:~icons/… path).
Logs
Error: ENOENT: no such file or directory, open '/…/_virtual_~demo'
Environment
unplugin: latest (also present on current main)
webpack: 5
Also seen with Next.js webpack (
next dev) when the filesystem cache is enabledReproduction
On current main, this unit test fails with ENOENT on
_virtual_~demo:The case that fails fakes a skipped
resolveId(a resolver already returns the_virtual_path). That is the same skip webpack does when it restores the path from its on-disk cache.A PR with that test and a fix is at #617.
The on-disk cache path was reproduced by starting and stopping a Next.js webpack app with the filesystem cache enabled. After a restart, compile fails with ENOENT on
_virtual_…until the placeholder is created again.Describe the bug
On webpack, unplugin serves modules that are not real files by creating an empty placeholder in memory during
resolveIdand pointing the module at a made-up_virtual_path. The plugin'sloadhook supplies the real source.Webpack then stores that
_virtual_path in its on-disk cache. The placeholder never reaches disk, so a new process starts without it.When the cache is reused, webpack already knows the path and skips
resolveId. It then opens the path and fails with ENOENT.This shows up after a
next devrestart, or a CI or Vercel build that reuses.next/cache.I have a PR for this: #617.
Additional context
Downstream report: unplugin/unplugin-icons#206
Same family as #32 (that issue used the older
virtual:~icons/…path).Logs
Error: ENOENT: no such file or directory, open '/…/_virtual_~demo'