Description
When vinext is installed as an npm package (rather than a symlinked local dependency), vite dev fails with:
✘ [ERROR] Could not resolve "virtual:vinext-rsc-entry"
node_modules/.pnpm/[email protected]_.../node_modules/vinext/dist/server/app-router-entry.js:15:23:
15 │ import rscHandler from "virtual:vinext-rsc-entry";
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~
This happens during esbuild's dependency optimization pass. The optimizer scans vinext/dist/server/app-router-entry.js, encounters the virtual:vinext-rsc-entry import, and fails because virtual modules only exist at Vite plugin resolution time — not during esbuild's pre-bundling scan.
Why this wasn't an issue before
When vinext is a symlinked package ("vinext": "link:../vinext/packages/vinext"), Vite automatically excludes linked packages from dependency optimization. Once installed from npm ("vinext": "^0.0.1"), esbuild starts scanning it and hits the unresolvable virtual imports.
The error occurs in multiple Vite environments (client, rsc, ssr) since app-router-entry.js can be pulled into the dep optimization graph from any of them.
Proposed fix
The vinext plugin should add an esbuild plugin in its config() hook to externalize its own virtual modules during dependency optimization:
// In the vinext plugin config() hook
config() {
return {
optimizeDeps: {
esbuildOptions: {
plugins: [{
name: "vinext-externalize-virtual",
setup(build) {
build.onResolve({ filter: /^virtual:vinext-/ }, (args) => ({
path: args.path,
external: true,
}));
},
}],
},
},
};
}
This is targeted — it only externalizes vinext's own virtual:vinext-* modules during the esbuild scan, without affecting pre-bundling of anything else.
An alternative (less targeted) approach would be to add "vinext" to optimizeDeps.exclude for all environments, but this prevents pre-bundling of all vinext exports even when unnecessary.
Current workaround
Users can add this to their vite.config.ts:
export default defineConfig({
optimizeDeps: {
exclude: ["vinext"],
esbuildOptions: {
plugins: [{
name: "externalize-virtual-modules",
setup(build) {
build.onResolve({ filter: /^virtual:/ }, (args) => ({
path: args.path,
external: true,
}));
},
}],
},
},
environments: {
rsc: {
optimizeDeps: {
exclude: ["vinext"],
},
},
ssr: {
optimizeDeps: {
exclude: ["vinext"],
},
},
},
});
This needs to cover all three environments (client via top-level, rsc, ssr) to prevent the error in each.
Description
When vinext is installed as an npm package (rather than a symlinked local dependency),
vite devfails with:This happens during esbuild's dependency optimization pass. The optimizer scans
vinext/dist/server/app-router-entry.js, encounters thevirtual:vinext-rsc-entryimport, and fails because virtual modules only exist at Vite plugin resolution time — not during esbuild's pre-bundling scan.Why this wasn't an issue before
When vinext is a symlinked package (
"vinext": "link:../vinext/packages/vinext"), Vite automatically excludes linked packages from dependency optimization. Once installed from npm ("vinext": "^0.0.1"), esbuild starts scanning it and hits the unresolvable virtual imports.The error occurs in multiple Vite environments (client, rsc, ssr) since
app-router-entry.jscan be pulled into the dep optimization graph from any of them.Proposed fix
The vinext plugin should add an esbuild plugin in its
config()hook to externalize its own virtual modules during dependency optimization:This is targeted — it only externalizes vinext's own
virtual:vinext-*modules during the esbuild scan, without affecting pre-bundling of anything else.An alternative (less targeted) approach would be to add
"vinext"tooptimizeDeps.excludefor all environments, but this prevents pre-bundling of all vinext exports even when unnecessary.Current workaround
Users can add this to their
vite.config.ts:This needs to cover all three environments (client via top-level, rsc, ssr) to prevent the error in each.