Feature: Generalized `ssrLoadModule()`
See original GitHub issueClear and concise description of the problem
Vite uses html files as entry points at both dev and build time. I created a plugin that abstracts this by generating the html content with an esm module before vite internally transforms it. During dev, is relies on ViteDevServer.ssrLoadModule()
as if it was a form of dynamic import()
but with vite transforms and fast invalidation.
But there are two major problems that get in the way of many important plugin use cases:
ssrLoadModule()
was made to load “client-type” code in node, failing to load anything likeimport fs from "fs/promises"
(within the normal vite dev configuration, at least).require()
will not work as a substitute forssrLoadModule()
.ssrLoadModule()
relies on aViteDevServer
, meaning that there is no way to apply its value (of applying vite transforms to e.g.(j|t)sx?
modules) during vite’s build mode.
This has forced my plugin into a corner of only being able to work with vanilla node during build time and not being allowed to import any node api’s (even dynamically within an if (false)
block!) during dev time. This makes my “lowest common denominator” allowed code almost useless, for arbitrary reasons.
Suggested solution
Snowpack has already declared the intention of moving towards fully generalized node SSR, which is exactly what we need. The best solution is basically to integrate what my plugin was aiming to implement directly into vite (abstract index.html as the entry point). But the easiest solution is to simply generalize ssrLoadModule()
into a version that:
- Explicitly is made to load anything that vite can process as if it were just a dynamic
import()
of node esm - Works with a module graph that does not necessarily have to be inside a
ViteDevServer
, enabling its usage within e.g. a build plugin’sload()
hook just as easily as in dev server middleware
Alternative
I hacked together a vite-incompatible function that simply built a temporary node esm file out of my prerendering code (including JSX) using esbuild and import()
ed that file as file:/temporarily/built/module.mjs?cache-buster=Math.random()
. It worked exactly how I expected as a proof of concept, with the only issues being efficiency for caching/invalidation (vite’s module graph is valuable here) and that it was incompatible with vite’s plugins (I had to hack the jsxInject
, any variable define
’s, and had no automatic path rebasing).
Obviously, a vite-native version would be far more streamlined and allow for many more useful plugin applications.
Additional context
No response
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn’t already an issue that request the same feature to avoid creating a duplicate.
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Hi @wlib. I wonder if this feature request still needed?
ssrLoadModule
is able to load node-only code withimport fs from "fs/promises"
IIRC, so this should work today.Transforming files in build mode should use normal Vite plugins as you have more control of how the final build output/chunks comes out. I don’t quite understand how
ssrLoadModule
should affect build mode? Hope you can clarify more on that.I think ultimately the ecosystem has grown a lot recently on this area, especially with Vitest spearheading the usage of Vite’s SSR transforms in NodeJS. For example, vite-node is used to power Vitest by leveraging Vite as a Node runtime.
Closing due to lack of response, but I think the above comment covers what this issue is proposing.