Skip to content

fix(vite): only skip vite-* WebSocket upgrades destined for Vite's HMR base#4291

Draft
pi0x wants to merge 1 commit into
mainfrom
fix/vite-ws
Draft

fix(vite): only skip vite-* WebSocket upgrades destined for Vite's HMR base#4291
pi0x wants to merge 1 commit into
mainfrom
fix/vite-ws

Conversation

@pi0x

@pi0x pi0x commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

In dev mode, Nitro's Vite integration installed an upgrade listener that skipped every WebSocket upgrade whose Sec-WebSocket-Protocol started with vite-. The intent — don't fight Vite's own HMR socket — was right, but the condition was too broad: it keyed off the subprotocol alone and ignored the request path.

As a result, a Nitro route that reverse-proxies an upstream Vite dev server never received the upstream's proxied HMR upgrade (vite-hmr on a non-HMR path): Nitro skipped it and outer Vite ignored it (wrong path), so the socket hung in pending forever.

Fix

Mirror Vite's own claim condition in configureViteDevServer (src/build/vite/dev.ts): only defer to Vite when the subprotocol is vite-hmr/vite-ping and the request path equals Vite's resolved HMR base. Also account for server.hmr.{server,port,path} — when HMR runs on a separate server/port, Vite attaches no listener here, so Nitro must not defer.

Tests

test/unit/vite-ws.test.ts spins up a real Nitro+Vite dev server with a WebSocket handler on a non-HMR path and performs a raw vite-hmr upgrade handshake. It fails (hangs to timeout) on the old code and passes with the fix; a plain upgrade is covered as a control. pnpm typecheck and pnpm fmt are clean.

🤖 Generated with Claude Code

…R base

The dev-server upgrade handler skipped every upgrade whose subprotocol
started with `vite-`, to avoid colliding with Vite's HMR socket. But Vite
only claims an upgrade when the subprotocol is `vite-hmr`/`vite-ping` AND
the path equals its HMR base. The over-broad skip meant Nitro routes that
reverse-proxy an upstream Vite dev server never received the proxied HMR
upgrade — it hung in `pending`. Mirror Vite's exact claim condition
(protocol AND path) and account for `server.hmr.{server,port,path}` so we
don't defer when Vite isn't even listening on this server.

Includes a regression test (test/unit/vite-ws.test.ts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented May 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nitro.build Ready Ready Preview, Comment May 29, 2026 7:25am

Request Review

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a588110-3aee-4655-ad99-d2741762f494

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/vite-ws

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new

pkg-pr-new Bot commented May 29, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/nitro@4291

commit: 1153ae6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants