fix(plugin-rsc): cjs to esm interop helper doesn't handle native/external cjs import properly#1092
Conversation
reproduced call stack: ```text [examples/basic:dev] 11:58:49 PM [vite] Internal server error: Class extends value [object Module] is not a constructor or null at eval (...\vite-plugin-react\node_modules\.pnpm\@vitejs+test-dep-cjs-events_287fa3db95bd309409d973813ed1549a\node_modules\@vitejs\test-dep-cjs-events-extend\index.js:3:34) at async ESModulesEvaluator.runInlinedModule (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:913:3) at async ModuleRunner.directRequest (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:1146:59) at async ModuleRunner.cachedRequest (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:1053:73) at async eval (...\vite-plugin-react\packages\plugin-rsc\examples\basic\src\routes\cjs-builtin-interop\server.tsx:1:1) at async ESModulesEvaluator.runInlinedModule (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:913:3) at async ModuleRunner.directRequest (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:1146:59) at async ModuleRunner.cachedRequest (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:1053:73) at async eval (...\vite-plugin-react\packages\plugin-rsc\examples\basic\src\routes\root.tsx:59:1) at async ESModulesEvaluator.runInlinedModule (.../vite-plugin-react/node_modules/.pnpm/vite@7.3.1_@types+node@24.1_8836aae8899929c20df59ea37bacc8d4/node_modules/vite/dist/node/module-runner.js:913:3) ```
…s import properly this is to fix issue vitejs#1087 This change enhances the cjs import check to cover the common Node cjs to esm wrapping behavior, where the esm wrapper namespace object is equivalent to the default export except the type differences and the default and named export of the default itself. the reproduce test now passes with this fix.
|
Thanks for PR! Will take a look. Your test case looks good, but can you also explain what's the actual package you hit the issue? |
sure thing! One of the real cases is that we have a dependency on the "ws" package, where the websocket/websocker-server.js is having exactly the same issue as the test case I added in the PR: https://github.com/websockets/ws/blob/master/lib/websocket.js |
commit: |
|
Thanks for reference. In this case, |
|
That said, this fixes genuine bugs so I'm happy to merge this. Can you test pkg.pr.new in #1092 (comment) to confirm if this fix is sufficient for your use case? (as I adjusted the interop slightly) |
One of the things the team decided is to bundling everything for ssr/rsc to make the server side deployment easier(and potentially better performance without having to resolve the external dependencies at runtime), that's why our vite config is very aggressive with "noExternal". I am happy to learn your perspective on what the benefits or trade-offs are by making dependencies like |
|
Right, bundling server output is actually legitimate as far as I know, but that can be done at separate build pipeline after vite build. Alternatively, you can also configure |
that seems to be a better solution, let me try that out, thanks for the suggestion. I also realized that Vite dev and build modes are quite different during debugging of this issue, which makes me wonder what are other gotchas that we'd better to be aware and config dev mode intentionally different, if there are such, please kindly share, thanks! |
confirming that this fix is sufficient for my use case, please feel free to merge it |
|
Thanks for contribution! |
|
The fix is released in v0.5.18 https://github.com/vitejs/vite-plugin-react/releases/tag/plugin-rsc%400.5.18 |
Description
This change added a reproduce test for the problem that discovered by issue #1087
The test would fail without this fix and passes with this fix.
When it fails, it is exactly the same error described in issue #1087
The fix is to leverage the Node cjs to esm wrapping behavior, where the wrapped esm namespace of the cjs module is a duplicate of the default export, with additional properties of the default and its named export.
The fix is also considered "safe" and won't break the consumer code, because the fix is inheriently checking that the default is equivalent to the namespace object by comparing all the properties.