diff --git a/packages/bundler-webpack/src/server/server.ts b/packages/bundler-webpack/src/server/server.ts index b6296e867bae..71b1453a56ef 100644 --- a/packages/bundler-webpack/src/server/server.ts +++ b/packages/bundler-webpack/src/server/server.ts @@ -4,7 +4,7 @@ import type { Stats } from '@umijs/bundler-webpack/compiled/webpack'; import webpack, { Configuration, } from '@umijs/bundler-webpack/compiled/webpack'; -import { getDevBanner, lodash, logger } from '@umijs/utils'; +import { getDevBanner, lodash, logger, portfinder } from '@umijs/utils'; import cors from 'cors'; import { createReadStream, existsSync } from 'fs'; import http from 'http'; @@ -235,24 +235,47 @@ export async function createServer(opts: IOpts): Promise { return null; } - ws = createWebSocketServer(server); + const protocol = userConfig.https ? 'https:' : 'http:'; + const basePort = opts.port || 8000; - ws.wss.on('connection', (socket) => { - if (stats) { - sendStats(getStats(stats), false, socket); + const parseSocketServerAddress = async () => { + if (!process.env.SOCKET_SERVER) return basePort; + const { port } = new URL(process.env.SOCKET_SERVER); + const startPort = Number(port) || basePort; + try { + const hmrPort = await portfinder.getPortPromise({ + port: startPort, + stopPort: startPort + 1, + }); + if (port && startPort !== hmrPort) { + console.log( + `[SOCKET_SERVER] hmr port changed from ${port} to ${basePort}`, + ); + return undefined; + } + return startPort === basePort ? undefined : startPort; + } catch (e) { + console.log(`[SOCKET_SERVER] hmr port not found, use ${basePort}`); + return undefined; } - }); - - const protocol = userConfig.https ? 'https:' : 'http:'; - const port = opts.port || 8000; + }; - server.listen(port, () => { - const banner = getDevBanner(protocol, opts.host, port); + const hmrPort = await parseSocketServerAddress(); + server.listen(basePort, () => { + const banner = getDevBanner(protocol, opts.host, basePort); console.log(banner.before); logger.ready(banner.main); console.log(banner.after); }); + ws = createWebSocketServer(server, hmrPort); + + ws.wss.on('connection', (socket) => { + if (stats) { + sendStats(getStats(stats), false, socket); + } + }); + return server; } diff --git a/packages/bundler-webpack/src/server/ws.ts b/packages/bundler-webpack/src/server/ws.ts index addf2de591c2..15265364ed2c 100644 --- a/packages/bundler-webpack/src/server/ws.ts +++ b/packages/bundler-webpack/src/server/ws.ts @@ -7,10 +7,16 @@ import WebSocket from '../../compiled/ws'; export function createWebSocketServer( server: HttpServer | HttpsServer | Http2Server | Server, + port?: number | undefined, ) { - const wss = new WebSocket.Server({ - noServer: true, - }); + let wss: WebSocket.Server; + if (port) { + wss = new WebSocket.Server({port}); + } else { + wss = new WebSocket.Server({ + noServer: true, + }); + } server.on('upgrade', (req, socket, head) => { if (req.headers['sec-websocket-protocol'] === 'webpack-hmr') {