From b2a5e1dd6f193f1ee4cee0e426766f158dc50a23 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Fri, 16 Aug 2024 18:12:42 +0900 Subject: [PATCH 01/15] fix: use websocket to test server liveness before client reload --- packages/vite/src/client/client.ts | 29 ++++++++++++----------------- packages/vite/src/node/server/ws.ts | 7 ++++++- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index ef4d6ad78b9e50..d32e30beba8af4 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -328,24 +328,19 @@ async function waitForSuccessfulPing( hostAndPath: string, ms = 1000, ) { - const pingHostProtocol = socketProtocol === 'wss' ? 'https' : 'http' - - const ping = async () => { - // A fetch on a websocket URL will return a successful promise with status 400, - // but will reject a networking error. - // When running on middleware mode, it returns status 426, and an cors error happens if mode is not no-cors - try { - await fetch(`${pingHostProtocol}://${hostAndPath}`, { - mode: 'no-cors', - headers: { - // Custom headers won't be included in a request with no-cors so (ab)use one of the - // safelisted headers to identify the ping request - Accept: 'text/x-vite-ping', - }, + async function ping() { + const socket = new WebSocket( + `${socketProtocol}://${hostAndPath}`, + 'vite-ping', + ) + return new Promise((resolve) => { + socket.addEventListener('open', () => { + resolve(true) }) - return true - } catch {} - return false + socket.addEventListener('error', () => { + resolve(false) + }) + }) } if (await ping()) { diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts index d0bffcdce4f8a0..3593fafbb19286 100644 --- a/packages/vite/src/node/server/ws.ts +++ b/packages/vite/src/node/server/ws.ts @@ -138,7 +138,9 @@ export function createWebSocketServer( wss = new WebSocketServerRaw({ noServer: true }) hmrServerWsListener = (req, socket, head) => { if ( - req.headers['sec-websocket-protocol'] === HMR_HEADER && + [HMR_HEADER, 'vite-ping'].includes( + req.headers['sec-websocket-protocol']!, + ) && req.url === hmrBase ) { wss.handleUpgrade(req, socket as Socket, head, (ws) => { @@ -173,6 +175,9 @@ export function createWebSocketServer( } wss.on('connection', (socket) => { + if (socket.protocol === 'vite-ping') { + return + } socket.on('message', (raw) => { if (!customListeners.size) return let parsed: any From ff87b077ef3e99623a120a8d07862580757d2a82 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 17 Aug 2024 11:58:02 +0900 Subject: [PATCH 02/15] test: add e2e --- .../__tests__/client-reload.spec.ts | 64 +++++++++++++++++++ playground/client-reload/__tests__/serve.ts | 6 ++ playground/client-reload/index.html | 4 ++ playground/client-reload/package.json | 12 ++++ playground/client-reload/vite.config.ts | 5 ++ playground/test-utils.ts | 2 + 6 files changed, 93 insertions(+) create mode 100644 playground/client-reload/__tests__/client-reload.spec.ts create mode 100644 playground/client-reload/__tests__/serve.ts create mode 100644 playground/client-reload/index.html create mode 100644 playground/client-reload/package.json create mode 100644 playground/client-reload/vite.config.ts diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts new file mode 100644 index 00000000000000..8c8d6eeb1834b2 --- /dev/null +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -0,0 +1,64 @@ +import path from 'node:path' +import { type ServerOptions, createServer } from 'vite' +import { describe, expect, onTestFinished, test } from 'vitest' +import { hmrPorts, isServe, page, ports } from '~utils' + +async function testClientReload(serverOptions: ServerOptions) { + // start server + const server = await createServer({ + root: path.resolve(import.meta.dirname, '..'), + logLevel: 'silent', + server: { + strictPort: true, + ...serverOptions, + }, + }) + onTestFinished(() => server.close()) + + await server.listen() + const serverUrl = server.resolvedUrls.local[0] + + // open page + await page.goto(serverUrl) + + // input state + await page.locator('input').fill('hello') + + // restart + const reloadPromise = page.waitForEvent('load') + await server.restart() + + // wait for reload and check state is cleared + await reloadPromise + await expect.poll(() => page.locator('input').textContent()).toBe('') +} + +describe.runIf(isServe)('client-reload', () => { + test('default', async () => { + await testClientReload({ + port: ports['client-reload'], + }) + }) + + test('custom hmr port', async () => { + await testClientReload({ + port: ports['client-reload'], + hmr: { + port: hmrPorts['client-reload'], + }, + }) + }) + + test('custom hmr port and cross origin isolation', async () => { + await testClientReload({ + port: ports['client-reload'], + hmr: { + port: hmrPorts['client-reload'], + }, + headers: { + 'Cross-Origin-Embedder-Policy': 'require-corp', + 'Cross-Origin-Opener-Policy': 'same-origin', + }, + }) + }) +}) diff --git a/playground/client-reload/__tests__/serve.ts b/playground/client-reload/__tests__/serve.ts new file mode 100644 index 00000000000000..1d33d8064a44b4 --- /dev/null +++ b/playground/client-reload/__tests__/serve.ts @@ -0,0 +1,6 @@ +// do nothing here since server is managed inside spec +export async function serve(): Promise<{ close(): Promise }> { + return { + close: () => Promise.resolve(), + } +} diff --git a/playground/client-reload/index.html b/playground/client-reload/index.html new file mode 100644 index 00000000000000..4d68bf74d3cb00 --- /dev/null +++ b/playground/client-reload/index.html @@ -0,0 +1,4 @@ + +

Test Client Reload

+ + diff --git a/playground/client-reload/package.json b/playground/client-reload/package.json new file mode 100644 index 00000000000000..a6fa570c64ffe7 --- /dev/null +++ b/playground/client-reload/package.json @@ -0,0 +1,12 @@ +{ + "name": "@vitejs/test-client-reload", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "debug": "node --inspect-brk ../../packages/vite/bin/vite", + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + } +} diff --git a/playground/client-reload/vite.config.ts b/playground/client-reload/vite.config.ts new file mode 100644 index 00000000000000..4c9c4be6ba0c82 --- /dev/null +++ b/playground/client-reload/vite.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + server: {}, +}) diff --git a/playground/test-utils.ts b/playground/test-utils.ts index f46bc3c95389cf..6f6bf644714cd4 100644 --- a/playground/test-utils.ts +++ b/playground/test-utils.ts @@ -46,6 +46,7 @@ export const ports = { 'css/postcss-plugins-different-dir': 5006, 'css/dynamic-import': 5007, 'css/lightningcss-proxy': 5008, + 'client-reload': 5009, } export const hmrPorts = { 'optimize-missing-deps': 24680, @@ -57,6 +58,7 @@ export const hmrPorts = { 'css/lightningcss-proxy': 24686, json: 24687, 'ssr-conditions': 24688, + 'client-reload': 24689, } const hexToNameMap: Record = {} From 90e657166615cc3e4896072f59edfce1371c7d1e Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 17 Aug 2024 12:00:56 +0900 Subject: [PATCH 03/15] test: cleanup --- playground/client-reload/__tests__/client-reload.spec.ts | 4 ++-- playground/client-reload/index.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index 8c8d6eeb1834b2..fa34679a456de3 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -28,9 +28,9 @@ async function testClientReload(serverOptions: ServerOptions) { const reloadPromise = page.waitForEvent('load') await server.restart() - // wait for reload and check state is cleared + // wait for reload and also check the state is reset await reloadPromise - await expect.poll(() => page.locator('input').textContent()).toBe('') + expect(await page.textContent('input')).toBe('') } describe.runIf(isServe)('client-reload', () => { diff --git a/playground/client-reload/index.html b/playground/client-reload/index.html index 4d68bf74d3cb00..7e78f23e2d5f54 100644 --- a/playground/client-reload/index.html +++ b/playground/client-reload/index.html @@ -1,4 +1,4 @@

Test Client Reload

- + From 68b3fb5562d92198b3374afc0f17ffd2df88eda9 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Fri, 27 Sep 2024 10:53:43 +0900 Subject: [PATCH 04/15] chore: lockfile --- pnpm-lock.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00995545b69a55..421ed89fa217ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -522,6 +522,8 @@ importers: specifier: ^0.11.4 version: 0.11.4 + playground/client-reload: {} + playground/config/packages/entry: dependencies: '@vite/test-config-plugin-module-condition': From dc024bf1c5f2e5a9e53eff2bba226274adf2b1ed Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Fri, 27 Sep 2024 12:25:28 +0900 Subject: [PATCH 05/15] test: tweak (but still flaky) --- .../__tests__/client-reload.spec.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index fa34679a456de3..0d4824ab4694f6 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -18,18 +18,24 @@ async function testClientReload(serverOptions: ServerOptions) { await server.listen() const serverUrl = server.resolvedUrls.local[0] - // open page + // open page and wait for connection + const connectedPromise = page.waitForEvent('console', { + predicate: (message) => message.text().includes('[vite] connected.'), + timeout: 5000, + }) await page.goto(serverUrl) + await connectedPromise // input state await page.locator('input').fill('hello') - // restart - const reloadPromise = page.waitForEvent('load') + // restart and wait for reconnection after reload + const reConnectedPromise = page.waitForEvent('console', { + predicate: (message) => message.text().includes('[vite] connected.'), + timeout: 5000, + }) await server.restart() - - // wait for reload and also check the state is reset - await reloadPromise + await reConnectedPromise expect(await page.textContent('input')).toBe('') } From 6ecb6d932f4dddd4ea63ee41f1e5c09b0a8bd86d Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Fri, 27 Sep 2024 12:26:59 +0900 Subject: [PATCH 06/15] test: more tweak --- playground/client-reload/__tests__/client-reload.spec.ts | 8 ++++---- playground/test-utils.ts | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index 0d4824ab4694f6..69c5ad90df8190 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -48,18 +48,18 @@ describe.runIf(isServe)('client-reload', () => { test('custom hmr port', async () => { await testClientReload({ - port: ports['client-reload'], + port: ports['client-reload/hmr-port'], hmr: { - port: hmrPorts['client-reload'], + port: hmrPorts['client-reload/hmr-port'], }, }) }) test('custom hmr port and cross origin isolation', async () => { await testClientReload({ - port: ports['client-reload'], + port: ports['client-reload/cross-origin'], hmr: { - port: hmrPorts['client-reload'], + port: hmrPorts['client-reload/cross-origin'], }, headers: { 'Cross-Origin-Embedder-Policy': 'require-corp', diff --git a/playground/test-utils.ts b/playground/test-utils.ts index a101504d4fdf45..b0b43544c27f5b 100644 --- a/playground/test-utils.ts +++ b/playground/test-utils.ts @@ -48,6 +48,8 @@ export const ports = { 'css/lightningcss-proxy': 5008, 'backend-integration': 5009, 'client-reload': 5010, + 'client-reload/hmr-port': 5011, + 'client-reload/cross-origin': 5012, } export const hmrPorts = { 'optimize-missing-deps': 24680, @@ -59,7 +61,8 @@ export const hmrPorts = { 'css/lightningcss-proxy': 24686, json: 24687, 'ssr-conditions': 24688, - 'client-reload': 24689, + 'client-reload/hmr-port': 24689, + 'client-reload/cross-origin': 24690, } const hexToNameMap: Record = {} From 9895a557ef344f259cd0db4a9d6a083ebbc71dcb Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 2 Oct 2024 11:42:42 +0900 Subject: [PATCH 07/15] test: skip some --- playground/client-reload/__tests__/client-reload.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index 69c5ad90df8190..f7f52120470843 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -39,14 +39,17 @@ async function testClientReload(serverOptions: ServerOptions) { expect(await page.textContent('input')).toBe('') } +// TODO: +// running all tests together is flaky. +// for now, run only the last one. describe.runIf(isServe)('client-reload', () => { - test('default', async () => { + test.skip('default', async () => { await testClientReload({ port: ports['client-reload'], }) }) - test('custom hmr port', async () => { + test.skip('custom hmr port', async () => { await testClientReload({ port: ports['client-reload/hmr-port'], hmr: { From 9a68df761e5acbfccbaa5c6451faea429424e36c Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 2 Oct 2024 12:18:42 +0900 Subject: [PATCH 08/15] test: retry --- .../__tests__/client-reload.spec.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index f7f52120470843..611057a39d1523 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -1,11 +1,17 @@ import path from 'node:path' -import { type ServerOptions, createServer } from 'vite' -import { describe, expect, onTestFinished, test } from 'vitest' +import { type ServerOptions, type ViteDevServer, createServer } from 'vite' +import { afterEach, describe, expect, test } from 'vitest' import { hmrPorts, isServe, page, ports } from '~utils' +let server: ViteDevServer + +afterEach(async () => { + await server?.close() +}) + async function testClientReload(serverOptions: ServerOptions) { // start server - const server = await createServer({ + server = await createServer({ root: path.resolve(import.meta.dirname, '..'), logLevel: 'silent', server: { @@ -13,7 +19,6 @@ async function testClientReload(serverOptions: ServerOptions) { ...serverOptions, }, }) - onTestFinished(() => server.close()) await server.listen() const serverUrl = server.resolvedUrls.local[0] @@ -41,7 +46,7 @@ async function testClientReload(serverOptions: ServerOptions) { // TODO: // running all tests together is flaky. -// for now, run only the last one. +// for now, run only the last one with retry. describe.runIf(isServe)('client-reload', () => { test.skip('default', async () => { await testClientReload({ @@ -58,7 +63,7 @@ describe.runIf(isServe)('client-reload', () => { }) }) - test('custom hmr port and cross origin isolation', async () => { + test('custom hmr port and cross origin isolation', { retry: 2 }, async () => { await testClientReload({ port: ports['client-reload/cross-origin'], hmr: { From 7ba013a3bf3d19dada76fdbb27c7f56cb33fbddb Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 13:58:15 +0900 Subject: [PATCH 09/15] fix: cleanup socket --- packages/vite/src/client/client.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index d2b269daf6e904..8c6b3b6d57803c 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -337,12 +337,21 @@ async function waitForSuccessfulPing( 'vite-ping', ) return new Promise((resolve) => { - socket.addEventListener('open', () => { + function onOpen() { resolve(true) - }) - socket.addEventListener('error', () => { + close() + } + function onError() { resolve(false) - }) + close() + } + function close() { + socket.removeEventListener('open', onOpen) + socket.removeEventListener('error', onError) + socket.close() + } + socket.addEventListener('open', onOpen) + socket.addEventListener('error', onError) }) } From 3af732cd5d690768f5f2579cb73a0e7f93ea1b61 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 14:21:25 +0900 Subject: [PATCH 10/15] test: restore --- playground/client-reload/__tests__/client-reload.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index 611057a39d1523..30b819595280df 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -48,13 +48,13 @@ async function testClientReload(serverOptions: ServerOptions) { // running all tests together is flaky. // for now, run only the last one with retry. describe.runIf(isServe)('client-reload', () => { - test.skip('default', async () => { + test('default', async () => { await testClientReload({ port: ports['client-reload'], }) }) - test.skip('custom hmr port', async () => { + test('custom hmr port', async () => { await testClientReload({ port: ports['client-reload/hmr-port'], hmr: { @@ -63,7 +63,7 @@ describe.runIf(isServe)('client-reload', () => { }) }) - test('custom hmr port and cross origin isolation', { retry: 2 }, async () => { + test('custom hmr port and cross origin isolation', async () => { await testClientReload({ port: ports['client-reload/cross-origin'], hmr: { From 6089d77ca01560cc96d9b164eb8c84068e751b30 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 3 Oct 2024 14:42:58 +0900 Subject: [PATCH 11/15] Revert "test: restore" This reverts commit 3af732cd5d690768f5f2579cb73a0e7f93ea1b61. --- playground/client-reload/__tests__/client-reload.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index 30b819595280df..611057a39d1523 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -48,13 +48,13 @@ async function testClientReload(serverOptions: ServerOptions) { // running all tests together is flaky. // for now, run only the last one with retry. describe.runIf(isServe)('client-reload', () => { - test('default', async () => { + test.skip('default', async () => { await testClientReload({ port: ports['client-reload'], }) }) - test('custom hmr port', async () => { + test.skip('custom hmr port', async () => { await testClientReload({ port: ports['client-reload/hmr-port'], hmr: { @@ -63,7 +63,7 @@ describe.runIf(isServe)('client-reload', () => { }) }) - test('custom hmr port and cross origin isolation', async () => { + test('custom hmr port and cross origin isolation', { retry: 2 }, async () => { await testClientReload({ port: ports['client-reload/cross-origin'], hmr: { From 91e7edf4bf9705b67e344142824eea5a0a0f23f9 Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:30:34 +0900 Subject: [PATCH 12/15] fix: error on wss listening but server not listening --- packages/vite/src/node/server/ws.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts index ee6fe8e33b6cfa..c379d76ede6b6c 100644 --- a/packages/vite/src/node/server/ws.ts +++ b/packages/vite/src/node/server/ws.ts @@ -159,14 +159,27 @@ export function createWebSocketServer( }) res.end(body) }) as Parameters[1] + // vite dev server in middleware mode + // need to call ws listen manually if (httpsOptions) { wsHttpServer = createHttpsServer(httpsOptions, route) } else { wsHttpServer = createHttpServer(route) } - // vite dev server in middleware mode - // need to call ws listen manually - wss = new WebSocketServerRaw({ server: wsHttpServer }) + wss = new WebSocketServerRaw({ noServer: true }) + wsHttpServer.on('upgrade', (req, socket, head) => { + const protocol = req.headers['sec-websocket-protocol']! + if (protocol === 'vite-ping' && server && !server.listening) { + // reject connection to tell the vite/client that the server is not ready + // if the http server is not listening + // because the ws server listens before the http server listens + req.destroy() + return + } + wss.handleUpgrade(req, socket as Socket, head, (ws) => { + wss.emit('connection', ws, req) + }) + }) } wss.on('connection', (socket) => { From a06e522c2e55f206f4424b34b57b857b835abacd Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 4 Oct 2024 17:41:26 +0900 Subject: [PATCH 13/15] test: disable ws for not used tests --- playground/js-sourcemap/test-ssr-dev.js | 1 + playground/ssr-html/test-network-imports.js | 1 + playground/ssr-html/test-stacktrace-runtime.js | 1 + playground/ssr-html/test-stacktrace.js | 1 + 4 files changed, 4 insertions(+) diff --git a/playground/js-sourcemap/test-ssr-dev.js b/playground/js-sourcemap/test-ssr-dev.js index c414f058517283..0e21a0ae80fe17 100644 --- a/playground/js-sourcemap/test-ssr-dev.js +++ b/playground/js-sourcemap/test-ssr-dev.js @@ -12,6 +12,7 @@ async function runTest() { server: { middlewareMode: true, hmr: false, + ws: false, }, define: { __testDefineObject: '{ "hello": "test" }', diff --git a/playground/ssr-html/test-network-imports.js b/playground/ssr-html/test-network-imports.js index 6e6a87d93d4219..d205acb12ee138 100644 --- a/playground/ssr-html/test-network-imports.js +++ b/playground/ssr-html/test-network-imports.js @@ -8,6 +8,7 @@ async function runTest(userRunner) { root: fileURLToPath(new URL('.', import.meta.url)), server: { middlewareMode: true, + ws: false, }, }) let mod diff --git a/playground/ssr-html/test-stacktrace-runtime.js b/playground/ssr-html/test-stacktrace-runtime.js index 0f4914dcbfe599..a53b7fbcdf8769 100644 --- a/playground/ssr-html/test-stacktrace-runtime.js +++ b/playground/ssr-html/test-stacktrace-runtime.js @@ -10,6 +10,7 @@ const server = await createServer({ root: fileURLToPath(new URL('.', import.meta.url)), server: { middlewareMode: true, + ws: false, }, }) diff --git a/playground/ssr-html/test-stacktrace.js b/playground/ssr-html/test-stacktrace.js index 327a8b4c423dae..85f48a82245ca7 100644 --- a/playground/ssr-html/test-stacktrace.js +++ b/playground/ssr-html/test-stacktrace.js @@ -29,6 +29,7 @@ const vite = await createServer({ logLevel: isTest ? 'error' : 'info', server: { middlewareMode: true, + ws: false, }, appType: 'custom', }) From 1c7a479913b0e1ec2dfb486d726bbb2337699fbc Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:00:16 +0900 Subject: [PATCH 14/15] test: restore --- playground/client-reload/__tests__/client-reload.spec.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/playground/client-reload/__tests__/client-reload.spec.ts b/playground/client-reload/__tests__/client-reload.spec.ts index 611057a39d1523..0872a2e17d4294 100644 --- a/playground/client-reload/__tests__/client-reload.spec.ts +++ b/playground/client-reload/__tests__/client-reload.spec.ts @@ -44,17 +44,14 @@ async function testClientReload(serverOptions: ServerOptions) { expect(await page.textContent('input')).toBe('') } -// TODO: -// running all tests together is flaky. -// for now, run only the last one with retry. describe.runIf(isServe)('client-reload', () => { - test.skip('default', async () => { + test('default', async () => { await testClientReload({ port: ports['client-reload'], }) }) - test.skip('custom hmr port', async () => { + test('custom hmr port', async () => { await testClientReload({ port: ports['client-reload/hmr-port'], hmr: { @@ -63,7 +60,7 @@ describe.runIf(isServe)('client-reload', () => { }) }) - test('custom hmr port and cross origin isolation', { retry: 2 }, async () => { + test('custom hmr port and cross origin isolation', async () => { await testClientReload({ port: ports['client-reload/cross-origin'], hmr: { From f22ae960f0f170d84c8a1d47fd458cdc552813cc Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:41:22 +0900 Subject: [PATCH 15/15] fix: dont crash on ws server error --- packages/vite/src/node/server/ws.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts index c379d76ede6b6c..c68ba6ce33cb13 100644 --- a/packages/vite/src/node/server/ws.ts +++ b/packages/vite/src/node/server/ws.ts @@ -180,6 +180,19 @@ export function createWebSocketServer( wss.emit('connection', ws, req) }) }) + wsHttpServer.on('error', (e: Error & { code: string }) => { + if (e.code === 'EADDRINUSE') { + config.logger.error( + colors.red(`WebSocket server error: Port is already in use`), + { error: e }, + ) + } else { + config.logger.error( + colors.red(`WebSocket server error:\n${e.stack || e.message}`), + { error: e }, + ) + } + }) } wss.on('connection', (socket) => {