Skip to content

Commit 711dd80

Browse files
divdavemsapphi-red
andauthored
fix: allow using vite as a proxy for another vite server (#13218)
Co-authored-by: sapphi-red <[email protected]>
1 parent eb75103 commit 711dd80

File tree

12 files changed

+108
-6
lines changed

12 files changed

+108
-6
lines changed

packages/vite/src/node/server/middlewares/proxy.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import httpProxy from 'http-proxy'
44
import type { Connect } from 'dep-types/connect'
55
import type { HttpProxy } from 'dep-types/http-proxy'
66
import colors from 'picocolors'
7-
import { HMR_HEADER } from '../ws'
87
import { createDebugger } from '../../utils'
98
import type { CommonServerOptions, ResolvedConfig } from '../..'
109

@@ -103,10 +102,9 @@ export function proxyMiddleware(
103102
if (doesProxyContextMatchUrl(context, url)) {
104103
const [proxy, opts] = proxies[context]
105104
if (
106-
(opts.ws ||
107-
opts.target?.toString().startsWith('ws:') ||
108-
opts.target?.toString().startsWith('wss:')) &&
109-
req.headers['sec-websocket-protocol'] !== HMR_HEADER
105+
opts.ws ||
106+
opts.target?.toString().startsWith('ws:') ||
107+
opts.target?.toString().startsWith('wss:')
110108
) {
111109
if (opts.rewrite) {
112110
req.url = opts.rewrite(url)

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'node:path'
12
import type { Server } from 'node:http'
23
import { STATUS_CODES, createServer as createHttpServer } from 'node:http'
34
import type { ServerOptions as HttpsServerOptions } from 'node:https'
@@ -101,9 +102,17 @@ export function createWebSocketServer(
101102
const host = (hmr && hmr.host) || undefined
102103

103104
if (wsServer) {
105+
let hmrBase = config.base
106+
const hmrPath = hmr ? hmr.path : undefined
107+
if (hmrPath) {
108+
hmrBase = path.posix.join(hmrBase, hmrPath)
109+
}
104110
wss = new WebSocketServerRaw({ noServer: true })
105111
wsServer.on('upgrade', (req, socket, head) => {
106-
if (req.headers['sec-websocket-protocol'] === HMR_HEADER) {
112+
if (
113+
req.headers['sec-websocket-protocol'] === HMR_HEADER &&
114+
req.url === hmrBase
115+
) {
107116
wss.handleUpgrade(req, socket as Socket, head, (ws) => {
108117
wss.emit('connection', ws, req)
109118
})
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { test } from 'vitest'
2+
import { editFile, page, untilUpdated, viteTestUrl } from '~utils'
3+
4+
test('proxy-hmr', async () => {
5+
await page.goto(viteTestUrl)
6+
const otherAppTextLocator = page.frameLocator('iframe').locator('.content')
7+
await untilUpdated(() => otherAppTextLocator.textContent(), 'other app')
8+
editFile('other-app/index.html', (code) =>
9+
code.replace('app', 'modified app'),
10+
)
11+
await untilUpdated(
12+
() => otherAppTextLocator.textContent(),
13+
'other modified app',
14+
)
15+
})
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// this is automatically detected by playground/vitestSetup.ts and will replace
2+
// the default e2e test serve behavior
3+
4+
import path from 'node:path'
5+
import { rootDir, setViteUrl } from '~utils'
6+
7+
export async function serve(): Promise<{ close(): Promise<void> }> {
8+
const vite = await import('vite')
9+
const rootServer = await vite.createServer({
10+
root: rootDir,
11+
logLevel: 'silent',
12+
})
13+
const otherServer = await vite.createServer({
14+
root: path.join(rootDir, 'other-app'),
15+
logLevel: 'silent',
16+
})
17+
18+
await Promise.all([rootServer.listen(), otherServer.listen()])
19+
const viteUrl = rootServer.resolvedUrls.local[0]
20+
setViteUrl(viteUrl)
21+
22+
return {
23+
async close() {
24+
await Promise.all([rootServer.close(), otherServer.close()])
25+
},
26+
}
27+
}

playground/proxy-hmr/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
root app<br />
2+
<iframe src="/anotherApp" style="border: 0"></iframe>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<span class="content">other app</span>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "@vitejs/test-other-app",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"preview": "vite preview"
10+
}
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { defineConfig } from 'vite'
2+
3+
export default defineConfig({
4+
base: '/anotherApp',
5+
server: {
6+
port: 9607,
7+
strictPort: true,
8+
},
9+
})

playground/proxy-hmr/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "@vitejs/test-proxy-hmr",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"preview": "vite preview"
10+
}
11+
}

playground/proxy-hmr/vite.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { defineConfig } from 'vite'
2+
3+
export default defineConfig({
4+
server: {
5+
port: 9606,
6+
proxy: {
7+
'/anotherApp': {
8+
target: 'http://localhost:9607',
9+
ws: true,
10+
},
11+
},
12+
},
13+
})

playground/test-utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export const ports = {
3030
'ssr-noexternal': 9603,
3131
'ssr-pug': 9604,
3232
'ssr-webworker': 9605,
33+
'proxy-hmr': 9606, // not imported but used in `proxy-hmr/vite.config.js`
34+
'proxy-hmr/other-app': 9607, // not imported but used in `proxy-hmr/other-app/vite.config.js`
3335
'css/postcss-caching': 5005,
3436
'css/postcss-plugins-different-dir': 5006,
3537
'css/dynamic-import': 5007,

pnpm-lock.yaml

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)