Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hmr): add server.hmr.retry option to solve frequent refresh caused by HMR WebSocket connection loss (#6089) #6090

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,12 +479,14 @@ export default defineConfig(async ({ command, mode }) => {

### server.hmr

- **Type:** `boolean | { protocol?: string, host?: string, port?: number, path?: string, timeout?: number, overlay?: boolean, clientPort?: number, server?: Server }`
- **Type:** `boolean | { protocol?: string, host?: string, port?: number, path?: string, timeout?: number, overlay?: boolean, clientPort?: number, server?: Server, retry?: boolean }`

Disable or configure HMR connection (in cases where the HMR websocket must use a different address from the http server).

Set `server.hmr.overlay` to `false` to disable the server error overlay.

Set `server.hmr.retry` to `false` to disable the HMR websocket reconnection.

`clientPort` is an advanced option that overrides the port only on the client side, allowing you to serve the websocket on a different port than the client code looks for it on. Useful if you're using an SSL proxy in front of your dev server.

When using `server.middlewareMode` or `server.https`, assigning `server.hmr.server` to your HTTP(S) server will process HMR connection requests through your server. This can be helpful when using self-signed certificates or when you want to expose Vite over a network on a single port.
Expand Down
5 changes: 5 additions & 0 deletions packages/vite/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ declare const __HMR_HOSTNAME__: string
declare const __HMR_PORT__: string
declare const __HMR_TIMEOUT__: number
declare const __HMR_ENABLE_OVERLAY__: boolean
declare const __HMR_RETRY__: boolean

console.log('[vite] connecting...')

Expand Down Expand Up @@ -219,6 +220,10 @@ async function waitForSuccessfulPing(ms = 1000) {
// ping server
socket.addEventListener('close', async ({ wasClean }) => {
if (wasClean) return
if (!__HMR_RETRY__) {
console.warn(`[vite] server connection lost. Manual refresh and try again.`)
return
}
console.log(`[vite] server connection lost. polling for restart...`)
await waitForSuccessfulPing()
location.reload()
Expand Down
2 changes: 2 additions & 0 deletions packages/vite/src/node/plugins/clientInjections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
const protocol = options.protocol || null
const timeout = options.timeout || 30000
const overlay = options.overlay !== false
const retry = options.retry === false ? false : true
let port: number | string | undefined
if (isObject(config.server.hmr)) {
port = config.server.hmr.clientPort || config.server.hmr.port
Expand All @@ -49,6 +50,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
.replace(`__HMR_PORT__`, JSON.stringify(port))
.replace(`__HMR_TIMEOUT__`, JSON.stringify(timeout))
.replace(`__HMR_ENABLE_OVERLAY__`, JSON.stringify(overlay))
.replace(`__HMR_RETRY__`, JSON.stringify(retry))
} else if (code.includes('process.env.NODE_ENV')) {
// replace process.env.NODE_ENV
return code.replace(
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/server/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface HmrOptions {
timeout?: number
overlay?: boolean
server?: Server
retry?: boolean
}

export interface HmrContext {
Expand Down