`vite.middleware` but for WinterCG `Request/Response`
Description
https://vitejs.dev/guide/ssr#setting-up-the-dev-server shows how to setup a dev server for ssr using express. with more and more server frameworks moving away from the Node.js Connect style API to be more Request/Response, I wonder if maybe Vite should have middlewares for those applications too?
Suggested solution
import { Hono } from 'hono'
import { createServer as createViteServer } from 'vite'
const app = new Hono()
const vite = await createViteServer({
server: { middlewareMode: "winter-cg" },
appType: 'custom'
})
app.use("*", (c, next) => {
// run the vite middlewares
await vite.middlewares(c.req, c.res, next)
});
or similar to make it compatible with req/res frameworks?
Alternative
No response
Additional context
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
Hi @juliusmarminge
I'm a creator of Hono. We are working on a similar project for Hono. Below is a dev server Vite plugin for Hono and fetch-based applications.
https://github.com/honojs/vite-plugins/tree/main/packages/dev-server
Whether or not Vite itself will implement these things is a matter of discussion, but for now, try this.
Hi @yusukebe , I think the dev-server plugin for Hono has a limitation with websockets currently, specifically for Node and Bun.
I'm wondering if it's possible to expose a createMiddleware function as an optional function from the package instead of a whole Vite plugin?
The limitation I encountered is with Websockets and mainly because of its forced-way of writing the Entry Point in Dev.
It forces you to always do this at the entry point:
export default {
fetch: app.fetch,
port: 3000,
};
as well as making sure your pnpm dev script calls vite
In Node
The dealbreaker with Node is that I can't use serve() during dev. Which I think is the only option for me to run websockets in Node: https://github.com/honojs/vite-plugins/issues/148
In Bun
Since I can't use Bun.serve in dev either, websockets don't seem to behave correctly. Even if you can attach websocket on the entry point: https://github.com/honojs/vite-plugins/issues/140
export default {
fetch: app.fetch,
port: 3000,
websocket: websocket
}
If there was a createViteToHonoMiddleware function, maybe we could have the option to do something like this at the handler instead:
import { resolve } from 'node:path';
if (privateConfig.NODE_ENV !== 'production') {
const root = resolve(__dirname, '../..');
// Instantiate Vite's development server and integrate its middleware to our server.
// ⚠️ We should instantiate it *only* in development. (It isn't needed in production
// and would unnecessarily bloat our server in production.)
const vite = await import('vite');
const viteDevMiddleware = (
await vite.createServer({
root,
server: {
middlewareMode: true,
hmr: { port: privateConfig.HMR_PORT },
},
})
).middlewares;
// @ts-ignore
app.use(createViteToHonoMiddleware(viteDevMiddleware)); // 👈 createViteToHonoMiddleware
}
And then be able to keep pnpm dev as tsx server.ts instead of vite.
I am basing this on the implementation here: https://github.com/blankeos/express-vike-websockets wherein both HMR and websockets work in a custom express server with Vite.
Hi @Blankeos
createViteToHonoMiddleware sounds good.
This is not only for the Vite matter, but if we can use the Connect in the Hono app, we can use vite.middlewares.
Awesome! @yusukebe Let me know if you want to move this discussion elsewhere, but after researching some more, I found that it's actually possible to overcome the limitation I mentioned. (But only on Node).
I have recreated the express-vike-websockets example above but in Hono:
https://github.com/blankeos/hono-vike-websockets
I think a createViteToHonoMiddleware that works on both Bun and Node would be cool. But I don't know if it's possible because Bun does not expose an http.Incoming for the Bun.serve like Node does with @hono/node-server serve(..) (but maybe I'm just missing something).
Credits to @phonzammi's solution on Discord for making Hono + Vite's
createServerwork.
Great Hono has a solution however a WinterCG middleware is still needed for other modern servers like Elysia, H3 (v2), etc..
@Blankeos https://github.com/vikejs/vike-node/blob/main/packages/vike-node/src/runtime/adapters/connectToWeb.ts Supports streaming and Bun.serve also
const webHandler = connectToWeb(vite.middlewares)
const response = await webHandler(request)
return response
I agree with @QuentinDutot. I think a general WinterCG solution should exist since Vite is part of the "modern web toolchain" and the connect middleware pattern is not (imo).
Is there any update on this?
I think a more standard pattern should also be supported.
I created universal-middleware to support this same vision more globally.
There are really powerful thing that we can do if we try to standardize those patterns. @universal-middlweware/express already supports casting Universal Middleware to Connect ones, so implementation in Vite could be done without too much pain at first IMO.
I have an example of such usage in vite-plugin-vercel.
In Vike, universal-middleware allows us to declare middlewares and make them run on any server we can, deploy anywhere we want, while only writing them once.
I stumbled onto that problem today, and considering we are in 2025 now, it feels more and more urgent to easlily integrate WinterCG compliant servers in the local ViteJS dev server! Having adapters is a workaround but they are fairly complicated and having a native support in Vite.js would bring a great performance improvement! 🙏
Ideally, Vite would only use web standards such as Request and Response — which already cover a lot of what Vite needs. That said, there is still a gap between web standards and what Vite needs. That's where universal-middleware steps in: it's a minimal library built around web standards to fill the gap between web standards and common needs.
FYI, in the context of building Vike, we tried to only use web standards but unfortunately realized that web standards alone aren't enough. That's why we built universal-middleware: it's the missing library that is unopinionated while filling the gap.
We think it also makes sense for Vite: replacing Connect middlewares with web standards + universal-middleware would enable Vite's middlewares to directly run in non-Connect environments.
Edit: for the Vite ecosystem folks who have access to #ecosystem on Vite's Discord, this reply was copied from a discussion we had on Discord.
I wonder if connect could be replaced with the unopinionated srvx which works in all runtimes and has node.js compat too
For people struggling with this: the easiest workaround I found is using https://github.com/mhart/fetch-to-node