Skip to content

feat: expose websocketPort config option for reverse proxy compatibility #261

@MatthewAry

Description

@MatthewAry

Clear and concise description of the problem

When the Vite dev server sits behind a reverse proxy (Caddy, nginx, etc.), the DevTools WebSocket connection fails. The proxy forwards HTTP traffic to Vite's main server port, but DevTools opens its own WebSocket server on a random port that the proxy doesn't know about.

createWsServer in packages/core/src/node/ws.ts picks the port with:

const port = options.portWebSocket ?? await getPort({ port: 7812, host, random: true })!

The client reads /.devtools/.connection.json, gets {"backend":"websocket","websocket":62480} (or whatever random port was chosen), and tries to connect directly to that port. Through the proxy, this fails silently.

In my local dev environment, I use caddy to help simulate HTTPS and to have a more "production like" networking experience while still having HMR and other conveniences.

Suggested solution

Add a websocketPort option to DevToolsConfig in packages/core/src/node/config.ts and wire it through to createDevToolsMiddleware.

The internal plumbing already supports it — CreateWsServerOptions already accepts portWebSocket. It's just not exposed through the config or passed by DevToolsServer in packages/core/src/node/plugins/server.ts.

The change would be:

  1. Add websocketPort?: number to DevToolsConfig
  2. Include it in normalizeDevToolsConfig
  3. In DevToolsServer.configureServer, read it from the resolved config and pass it as portWebSocket to createDevToolsMiddleware

Usage:

// vite.config.ts
export default defineConfig({
  devtools: {
    enabled: true,
    websocketPort: 7812,
  },
})

With a fixed port, users can configure their proxy to forward that port alongside Vite's main port.

Alternative

DevTools could reuse Vite's existing HMR WebSocket connection instead of opening a separate server. This would make it work behind any proxy that already supports Vite's dev server with no extra config. That's a much larger architectural change though — a config option for the port is a simpler path.

Additional context

In the meantime I have made for myself a small Vite plugin that intercepts requests to the DevTools inject script and returns an empty module when the Host header isn't localhost. This means DevTools only works on localhost — not through the proxy. Otherwise I will end up seeing Vite DevTools but would never be able to authenticate because it could never trigger an auth flow for me to see on the terminal.

As a side note:
The "Code of Conduct" link goes to a 404 but I checked it anyways.

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions