-
Notifications
You must be signed in to change notification settings - Fork 104
Description
HMR WebSocket port conflict when running multiple Nuxt apps simultaneously
Environment
- Nuxt: 4.2.2
- Vite: 7.3.0
- Node: 22.x
- OS: macOS
Description
When running multiple Nuxt apps in development mode simultaneously (e.g., in a monorepo), they conflict on the HMR WebSocket port 24678, even when custom vite.server.hmr.port is configured.
Reproduction
- Create two Nuxt apps in a monorepo
- Configure different ports for each app
- Configure custom HMR port for the second app:
// apps/storefront/nuxt.config.ts
export default defineNuxtConfig({
vite: {
server: {
hmr: {
port: 24680,
clientPort: 24680,
},
},
},
})- Run both apps simultaneously
- Second app fails with:
WebSocket server error: Port 24678 is already in use
Root Cause
Two issues cause this:
Issue 1: SSR environment creates WebSocket on default port
In @nuxt/vite-builder, when config.server.hmr.server is set (Nuxt sets this to share HTTP server), the getPort() call is skipped:
if (typeof config.server.hmr !== "object" || !config.server.hmr.server) {
// getPort() is called here - but this block is SKIPPED when hmr.server is set
}This means hmr.port is never assigned. Later, Vite's SSR environment (where hmr: false) tries to create a WebSocket and falls back to 24678.
Issue 2: User-defined HMR port is overwritten
When user sets vite.server.hmr.port, Nuxt's DevServerPlugin later sets hmr.server which causes Vite to share the HTTP server instead of using a standalone WebSocket on the user-specified port.
Proposed Fix
// In DevServerPlugin config()
const userHmrPort = nuxt.options.vite?.server?.hmr?.port;
const userClientPort = nuxt.options.vite?.server?.hmr?.clientPort;
if (userHmrPort) {
config.server = config.server || {};
// Override hmr config to use standalone WebSocket (don't set hmr.server)
config.server.hmr = {
port: userHmrPort,
clientPort: userClientPort || userHmrPort,
};
}
// Also: always assign HMR port even when hmr.server is set
const existingHmrPort = typeof config.server.hmr === 'object' ? config.server.hmr.port : undefined;
if (!existingHmrPort) {
const assignedPort = await getPort({ port: 24678, ... });
config.server.hmr.port = assignedPort;
}Related
- Vite issue: WebSocket server created on default port even when HMR is disabled vitejs/vite#21318 (SSR environment should not create WebSocket when
hmr: false)
Workaround
Apply patches to both @nuxt/vite-builder and vite packages (see attached patch files).