run icon indicating copy to clipboard operation
run copied to clipboard

HMR WebSocket fails - middlewareMode prevents Vite's WebSocket handler

Open etune opened this issue 1 month ago • 0 comments

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

  1. Run marko-run dev
  2. Access the dev server through any proxy (Cloudflare Tunnel, nginx, etc.)
  3. Open browser DevTools → Network → WS filter
  4. 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:

  1. Change middlewareMode: true to false
  2. Change devServer.middlewares.listen() to devServer.httpServer.listen()

etune avatar Nov 23 '25 02:11 etune