Summary
HMR WebSocket connections fail when using marko-run dev. The WebSocket upgrade request returns 404 instead of 101 Switching Protocols.
Environment
@marko/run: 0.9.3
vite: 7.2.2
- Node.js: 20.x
Reproduce Steps
- Run
marko-run dev
- Access the dev server through any proxy (Cloudflare Tunnel, nginx, etc.)
- Open browser DevTools → Network → WS filter
- Observe WebSocket returns 404, HMR doesn't work
Root Cause
In src/adapter/dev-server.ts:
server: { ...config?.server, middlewareMode: true }
Then in startDev:
const listener = devServer.middlewares.listen(port, ...);
The problem:
middlewareMode: true tells Vite NOT to create its own HTTP server (devServer.httpServer is null)
middlewares.listen() creates a NEW HTTP server
- This new server doesn't have Vite's WebSocket upgrade handler attached
- WebSocket upgrades get routed as HTTP GET → 404
Proof
- Raw
npx vite → WebSocket returns 101 Switching Protocols ✅
marko-run dev → WebSocket returns 404 ❌
Proposed Fix
// Don't use middlewareMode
server: { ...config?.server, middlewareMode: false }
// Use Vite's httpServer
devServer.httpServer.listen(port, ...);
Workaround
Users can use patch-package to patch node_modules/@marko/run/dist/adapter/index.js:
- Change
middlewareMode: true to false
- Change
devServer.middlewares.listen() to devServer.httpServer.listen()
Summary
HMR WebSocket connections fail when using
marko-run dev. The WebSocket upgrade request returns404instead of101 Switching Protocols.Environment
@marko/run: 0.9.3vite: 7.2.2Reproduce Steps
marko-run devRoot Cause
In
src/adapter/dev-server.ts:Then in
startDev:The problem:
middlewareMode: truetells Vite NOT to create its own HTTP server (devServer.httpServerisnull)middlewares.listen()creates a NEW HTTP serverProof
npx vite→ WebSocket returns101 Switching Protocols✅marko-run dev→ WebSocket returns404❌Proposed Fix
Workaround
Users can use
patch-packageto patchnode_modules/@marko/run/dist/adapter/index.js:middlewareMode: truetofalsedevServer.middlewares.listen()todevServer.httpServer.listen()