diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 157d60fded48fc..8fcb145fd0242c 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -102,9 +102,11 @@ function setupWebSocket( notifyListeners('vite:ws:disconnect', { webSocket: socket }) - console.log(`[vite] server connection lost. polling for restart...`) - await waitForSuccessfulPing(protocol, hostAndPath) - location.reload() + if (hasDocument) { + console.log(`[vite] server connection lost. polling for restart...`) + await waitForSuccessfulPing(protocol, hostAndPath) + location.reload() + } }) return socket @@ -182,18 +184,20 @@ async function handleMessage(payload: HMRPayload) { break case 'update': notifyListeners('vite:beforeUpdate', payload) - // if this is the first update and there's already an error overlay, it - // means the page opened with existing server compile error and the whole - // module script failed to load (since one of the nested imports is 500). - // in this case a normal update won't work and a full reload is needed. - if (isFirstUpdate && hasErrorOverlay()) { - window.location.reload() - return - } else { - if (enableOverlay) { - clearErrorOverlay() + if (hasDocument) { + // if this is the first update and there's already an error overlay, it + // means the page opened with existing server compile error and the whole + // module script failed to load (since one of the nested imports is 500). + // in this case a normal update won't work and a full reload is needed. + if (isFirstUpdate && hasErrorOverlay()) { + window.location.reload() + return + } else { + if (enableOverlay) { + clearErrorOverlay() + } + isFirstUpdate = false } - isFirstUpdate = false } await Promise.all( payload.updates.map(async (update): Promise => { @@ -251,21 +255,23 @@ async function handleMessage(payload: HMRPayload) { } case 'full-reload': notifyListeners('vite:beforeFullReload', payload) - if (payload.path && payload.path.endsWith('.html')) { - // if html file is edited, only reload the page if the browser is - // currently on that page. - const pagePath = decodeURI(location.pathname) - const payloadPath = base + payload.path.slice(1) - if ( - pagePath === payloadPath || - payload.path === '/index.html' || - (pagePath.endsWith('/') && pagePath + 'index.html' === payloadPath) - ) { + if (hasDocument) { + if (payload.path && payload.path.endsWith('.html')) { + // if html file is edited, only reload the page if the browser is + // currently on that page. + const pagePath = decodeURI(location.pathname) + const payloadPath = base + payload.path.slice(1) + if ( + pagePath === payloadPath || + payload.path === '/index.html' || + (pagePath.endsWith('/') && pagePath + 'index.html' === payloadPath) + ) { + pageReload() + } + return + } else { pageReload() } - return - } else { - pageReload() } break case 'prune': @@ -274,13 +280,15 @@ async function handleMessage(payload: HMRPayload) { break case 'error': { notifyListeners('vite:error', payload) - const err = payload.err - if (enableOverlay) { - createErrorOverlay(err) - } else { - console.error( - `[vite] Internal Server Error\n${err.message}\n${err.stack}`, - ) + if (hasDocument) { + const err = payload.err + if (enableOverlay) { + createErrorOverlay(err) + } else { + console.error( + `[vite] Internal Server Error\n${err.message}\n${err.stack}`, + ) + } } break } @@ -300,6 +308,7 @@ function notifyListeners(event: string, data: any): void { } const enableOverlay = __HMR_ENABLE_OVERLAY__ +const hasDocument = 'document' in globalThis function createErrorOverlay(err: ErrorPayload['err']) { clearErrorOverlay() diff --git a/packages/vite/src/client/overlay.ts b/packages/vite/src/client/overlay.ts index 33c9320f509b46..3b2bc8f4d76f6f 100644 --- a/packages/vite/src/client/overlay.ts +++ b/packages/vite/src/client/overlay.ts @@ -165,42 +165,40 @@ kbd { ` // Error Template -const template = - 'document' in globalThis - ? h( +const createTemplate = () => + h( + 'div', + { class: 'backdrop', part: 'backdrop' }, + h( + 'div', + { class: 'window', part: 'window' }, + h( + 'pre', + { class: 'message', part: 'message' }, + h('span', { class: 'plugin', part: 'plugin' }), + h('span', { class: 'message-body', part: 'message-body' }), + ), + h('pre', { class: 'file', part: 'file' }), + h('pre', { class: 'frame', part: 'frame' }), + h('pre', { class: 'stack', part: 'stack' }), + h( 'div', - { class: 'backdrop', part: 'backdrop' }, - h( - 'div', - { class: 'window', part: 'window' }, - h( - 'pre', - { class: 'message', part: 'message' }, - h('span', { class: 'plugin', part: 'plugin' }), - h('span', { class: 'message-body', part: 'message-body' }), - ), - h('pre', { class: 'file', part: 'file' }), - h('pre', { class: 'frame', part: 'frame' }), - h('pre', { class: 'stack', part: 'stack' }), - h( - 'div', - { class: 'tip', part: 'tip' }, - 'Click outside, press ', - h('kbd', {}, 'Esc'), - ' key, or fix the code to dismiss.', - h('br'), - 'You can also disable this overlay by setting ', - h('code', { part: 'config-option-name' }, 'server.hmr.overlay'), - ' to ', - h('code', { part: 'config-option-value' }, 'false'), - ' in ', - h('code', { part: 'config-file-name' }, hmrConfigName), - '.', - ), - ), - h('style', {}, templateStyle), - ) - : undefined + { class: 'tip', part: 'tip' }, + 'Click outside, press ', + h('kbd', {}, 'Esc'), + ' key, or fix the code to dismiss.', + h('br'), + 'You can also disable this overlay by setting ', + h('code', { part: 'config-option-name' }, 'server.hmr.overlay'), + ' to ', + h('code', { part: 'config-option-value' }, 'false'), + ' in ', + h('code', { part: 'config-file-name' }, hmrConfigName), + '.', + ), + ), + h('style', {}, templateStyle), + ) const fileRE = /(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g const codeframeRE = /^(?:>?\s*\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm @@ -216,9 +214,7 @@ export class ErrorOverlay extends HTMLElement { super() this.root = this.attachShadow({ mode: 'open' }) - if (template) { - this.root.appendChild(template) - } + this.root.appendChild(createTemplate()) codeframeRE.lastIndex = 0 const hasFrame = err.frame && codeframeRE.test(err.frame)