Skip to content

Commit 2f2b2df

Browse files
author
zhengjiaqi02
committed
feat(hmr): add server.hmr.retry option to solve frequent refresh caused by HMR WebSocket connection loss (vitejs#6089)
1 parent 61d076a commit 2f2b2df

File tree

4 files changed

+11
-1
lines changed

4 files changed

+11
-1
lines changed

docs/config/index.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,14 @@ export default defineConfig(async ({ command, mode }) => {
479479

480480
### server.hmr
481481

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

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

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

488+
Set `server.hmr.retry` to `false` to disable the HMR websocket reconnection.
489+
488490
`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.
489491

490492
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.

packages/vite/src/client/client.ts

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ declare const __HMR_HOSTNAME__: string
1818
declare const __HMR_PORT__: string
1919
declare const __HMR_TIMEOUT__: number
2020
declare const __HMR_ENABLE_OVERLAY__: boolean
21+
declare const __HMR_RETRY__: boolean
2122

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

@@ -219,6 +220,10 @@ async function waitForSuccessfulPing(ms = 1000) {
219220
// ping server
220221
socket.addEventListener('close', async ({ wasClean }) => {
221222
if (wasClean) return
223+
if (!__HMR_RETRY__) {
224+
console.warn(`[vite] server connection lost. Manual refresh and try again.`)
225+
return
226+
}
222227
console.log(`[vite] server connection lost. polling for restart...`)
223228
await waitForSuccessfulPing()
224229
location.reload()

packages/vite/src/node/plugins/clientInjections.ts

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
2323
const protocol = options.protocol || null
2424
const timeout = options.timeout || 30000
2525
const overlay = options.overlay !== false
26+
const retry = options.retry === false ? false : true
2627
let port: number | string | undefined
2728
if (isObject(config.server.hmr)) {
2829
port = config.server.hmr.clientPort || config.server.hmr.port
@@ -49,6 +50,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
4950
.replace(`__HMR_PORT__`, JSON.stringify(port))
5051
.replace(`__HMR_TIMEOUT__`, JSON.stringify(timeout))
5152
.replace(`__HMR_ENABLE_OVERLAY__`, JSON.stringify(overlay))
53+
.replace(`__HMR_RETRY__`, JSON.stringify(retry))
5254
} else if (code.includes('process.env.NODE_ENV')) {
5355
// replace process.env.NODE_ENV
5456
return code.replace(

packages/vite/src/node/server/hmr.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface HmrOptions {
2424
timeout?: number
2525
overlay?: boolean
2626
server?: Server
27+
retry?: boolean
2728
}
2829

2930
export interface HmrContext {

0 commit comments

Comments
 (0)