Skip to content

Commit a1301ed

Browse files
authored
feat(dev): reuse dev server port for websocket (#6476)
1 parent d04a11e commit a1301ed

File tree

18 files changed

+153
-176
lines changed

18 files changed

+153
-176
lines changed

.changeset/wicked-pandas-give.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
"@remix-run/dev": minor
3+
"@remix-run/react": minor
4+
"@remix-run/server-runtime": minor
5+
---
6+
7+
Reuse dev server port for WebSocket (Live Reload,HMR,HDR)
8+
9+
As a result the `webSocketPort`/`--websocket-port` option has been obsoleted.
10+
Additionally, scheme/host/port options for the dev server have been renamed.
11+
12+
Available options are:
13+
14+
| Option | flag | config | default |
15+
| -------------- | ------------------ | ---------------- | --------------------------------- |
16+
| Command | `-c` / `--command` | `command` | `remix-serve <server build path>` |
17+
| Scheme | `--scheme` | `scheme` | `http` |
18+
| Host | `--host` | `host` | `localhost` |
19+
| Port | `--port` | `port` | Dynamically chosen open port |
20+
| No restart | `--no-restart` | `restart: false` | `restart: true` |
21+
22+
Note that scheme/host/port options are for the _dev server_, not your app server.
23+
You probably don't need to use scheme/host/port option if you aren't configuring networking (e.g. for Docker or SSL).

integration/hmr-log-test.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,15 @@ import { createFixtureProject, css, js, json } from "./helpers/create-fixture";
99

1010
test.setTimeout(120_000);
1111

12-
let fixture = (options: {
13-
appServerPort: number;
14-
httpPort: number;
15-
webSocketPort: number;
16-
}) => ({
12+
let fixture = (options: { appPort: number; devPort: number }) => ({
1713
files: {
1814
"remix.config.js": js`
1915
module.exports = {
2016
serverModuleFormat: "cjs",
2117
tailwind: true,
2218
future: {
2319
unstable_dev: {
24-
httpPort: ${options.httpPort},
25-
webSocketPort: ${options.webSocketPort},
20+
port: ${options.devPort},
2621
},
2722
v2_routeConvention: true,
2823
v2_errorBoundary: true,
@@ -80,7 +75,7 @@ let fixture = (options: {
8075
})
8176
);
8277
83-
let port = ${options.appServerPort};
78+
let port = ${options.appPort};
8479
app.listen(port, () => {
8580
let build = require(BUILD_DIR);
8681
console.log('✅ app ready: http://localhost:' + port);
@@ -250,12 +245,9 @@ test("HMR", async ({ page }) => {
250245
});
251246

252247
let portRange = makeRange(4080, 4099);
253-
let appServerPort = await getPort({ port: portRange });
254-
let httpPort = await getPort({ port: portRange });
255-
let webSocketPort = await getPort({ port: portRange });
256-
let projectDir = await createFixtureProject(
257-
fixture({ appServerPort, httpPort, webSocketPort })
258-
);
248+
let appPort = await getPort({ port: portRange });
249+
let devPort = await getPort({ port: portRange });
250+
let projectDir = await createFixtureProject(fixture({ appPort, devPort }));
259251

260252
// spin up dev server
261253
let dev = execa("npm", ["run", "dev"], { cwd: projectDir });
@@ -270,7 +262,7 @@ test("HMR", async ({ page }) => {
270262
{ timeoutMs: 10_000 }
271263
);
272264

273-
await page.goto(`http://localhost:${appServerPort}`, {
265+
await page.goto(`http://localhost:${appPort}`, {
274266
waitUntil: "networkidle",
275267
});
276268

@@ -470,7 +462,7 @@ whatsup
470462
await page.getByText("Hello, planet").waitFor({ timeout: HMR_TIMEOUT_MS });
471463
await page.waitForLoadState("networkidle");
472464

473-
expect(devStderr()).toBe("");
465+
let stderr = devStderr();
474466
let withSyntaxError = `
475467
import { useLoaderData } from "@remix-run/react";
476468
export function shouldRevalidate(args) {
@@ -486,9 +478,15 @@ whatsup
486478
}
487479
`;
488480
fs.writeFileSync(indexPath, withSyntaxError);
489-
await wait(() => devStderr().includes('Expected ";" but found "efault"'), {
490-
timeoutMs: HMR_TIMEOUT_MS,
491-
});
481+
await wait(
482+
() =>
483+
devStderr()
484+
.replace(stderr, "")
485+
.includes('Expected ";" but found "efault"'),
486+
{
487+
timeoutMs: HMR_TIMEOUT_MS,
488+
}
489+
);
492490

493491
let withFix = `
494492
import { useLoaderData } from "@remix-run/react";

integration/hmr-test.ts

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,15 @@ import { createFixtureProject, css, js, json } from "./helpers/create-fixture";
99

1010
test.setTimeout(120_000);
1111

12-
let fixture = (options: {
13-
appServerPort: number;
14-
httpPort: number;
15-
webSocketPort: number;
16-
}) => ({
12+
let fixture = (options: { appPort: number; devPort: number }) => ({
1713
files: {
1814
"remix.config.js": js`
1915
module.exports = {
2016
serverModuleFormat: "cjs",
2117
tailwind: true,
2218
future: {
2319
unstable_dev: {
24-
httpPort: ${options.httpPort},
25-
webSocketPort: ${options.webSocketPort},
20+
port: ${options.devPort},
2621
},
2722
v2_routeConvention: true,
2823
v2_errorBoundary: true,
@@ -69,18 +64,17 @@ let fixture = (options: {
6964
const app = express();
7065
app.use(express.static("public", { immutable: true, maxAge: "1y" }));
7166
72-
const MODE = process.env.NODE_ENV;
7367
const BUILD_DIR = path.join(process.cwd(), "build");
7468
7569
app.all(
7670
"*",
7771
createRequestHandler({
7872
build: require(BUILD_DIR),
79-
mode: MODE,
73+
mode: process.env.NODE_ENV,
8074
})
8175
);
8276
83-
let port = ${options.appServerPort};
77+
let port = ${options.appPort};
8478
app.listen(port, () => {
8579
let build = require(BUILD_DIR);
8680
console.log('✅ app ready: http://localhost:' + port);
@@ -249,12 +243,9 @@ test("HMR", async ({ page }) => {
249243
});
250244

251245
let portRange = makeRange(3080, 3099);
252-
let appServerPort = await getPort({ port: portRange });
253-
let httpPort = await getPort({ port: portRange });
254-
let webSocketPort = await getPort({ port: portRange });
255-
let projectDir = await createFixtureProject(
256-
fixture({ appServerPort, httpPort, webSocketPort })
257-
);
246+
let appPort = await getPort({ port: portRange });
247+
let devPort = await getPort({ port: portRange });
248+
let projectDir = await createFixtureProject(fixture({ appPort, devPort }));
258249

259250
// spin up dev server
260251
let dev = execa("npm", ["run", "dev"], { cwd: projectDir });
@@ -269,7 +260,7 @@ test("HMR", async ({ page }) => {
269260
{ timeoutMs: 10_000 }
270261
);
271262

272-
await page.goto(`http://localhost:${appServerPort}`, {
263+
await page.goto(`http://localhost:${appPort}`, {
273264
waitUntil: "networkidle",
274265
});
275266

@@ -469,7 +460,7 @@ whatsup
469460
await page.getByText("Hello, planet").waitFor({ timeout: HMR_TIMEOUT_MS });
470461
await page.waitForLoadState("networkidle");
471462

472-
expect(devStderr()).toBe("");
463+
let stderr = devStderr();
473464
let withSyntaxError = `
474465
import { useLoaderData } from "@remix-run/react";
475466
export function shouldRevalidate(args) {
@@ -485,9 +476,15 @@ whatsup
485476
}
486477
`;
487478
fs.writeFileSync(indexPath, withSyntaxError);
488-
await wait(() => devStderr().includes('Expected ";" but found "efault"'), {
489-
timeoutMs: HMR_TIMEOUT_MS,
490-
});
479+
await wait(
480+
() =>
481+
devStderr()
482+
.replace(stderr, "")
483+
.includes('Expected ";" but found "efault"'),
484+
{
485+
timeoutMs: HMR_TIMEOUT_MS,
486+
}
487+
);
491488

492489
let withFix = `
493490
import { useLoaderData } from "@remix-run/react";

packages/remix-dev/__tests__/cli-test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,10 @@ describe("remix CLI", () => {
118118
119119
[unstable_dev]
120120
--command, -c Command used to run your app server
121-
--http-scheme HTTP(S) scheme for the dev server. Default: http
122-
--http-host HTTP(S) host for the dev server. Default: localhost
123-
--http-port HTTP(S) port for the dev server. Default: any open port
121+
--scheme Scheme for the dev server. Default: http
122+
--host Host for the dev server. Default: localhost
123+
--port Port for the dev server. Default: any open port
124124
--no-restart Do not restart the app server when rebuilds occur.
125-
--websocket-port WebSocket port for the dev server. Default: any open port
126125
\`init\` Options:
127126
--no-delete Skip deleting the \`remix.init\` script
128127
\`routes\` Options:

packages/remix-dev/cli/commands.ts

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,8 @@ export async function build(
177177
onWarning: warnOnce,
178178
};
179179
if (mode === "development" && config.future.unstable_dev) {
180-
let dev = await resolveDevBuild(config);
181-
options.devHttpOrigin = {
182-
scheme: dev.httpScheme,
183-
host: dev.httpHost,
184-
port: dev.httpPort,
185-
};
186-
options.devWebSocketPort = dev.webSocketPort;
180+
let origin = await resolveDevOrigin(config);
181+
options.devOrigin = origin;
187182
}
188183

189184
fse.emptyDirSync(config.assetsBuildDirectory);
@@ -216,20 +211,20 @@ export async function dev(
216211
remixRoot: string,
217212
flags: {
218213
debug?: boolean;
219-
port?: number; // TODO: remove for v2
220214

221215
// unstable_dev
222216
command?: string;
223-
httpScheme?: string;
224-
httpHost?: string;
225-
httpPort?: number;
217+
scheme?: string;
218+
host?: string;
219+
port?: number;
226220
restart?: boolean;
227-
websocketPort?: number;
228221
} = {}
229222
) {
230223
if (process.env.NODE_ENV && process.env.NODE_ENV !== "development") {
231224
console.warn(
232-
`Forcing NODE_ENV to be 'development'. Was: ${process.env.NODE_ENV}`
225+
`Forcing NODE_ENV to be 'development'. Was: ${JSON.stringify(
226+
process.env.NODE_ENV
227+
)}`
233228
);
234229
}
235230
process.env.NODE_ENV = "development";
@@ -471,49 +466,42 @@ let parseMode = (
471466

472467
let findPort = async () => getPort({ port: makeRange(3001, 3100) });
473468

474-
type DevBuildFlags = {
475-
httpScheme: string;
476-
httpHost: string;
477-
httpPort: number;
478-
webSocketPort: number;
469+
type DevOrigin = {
470+
scheme: string;
471+
host: string;
472+
port: number;
479473
};
480-
let resolveDevBuild = async (
474+
let resolveDevOrigin = async (
481475
config: RemixConfig,
482-
flags: Partial<DevBuildFlags> = {}
483-
): Promise<DevBuildFlags> => {
476+
flags: Partial<DevOrigin> = {}
477+
): Promise<DevOrigin> => {
484478
let dev = config.future.unstable_dev;
485479
if (dev === false) throw Error("This should never happen");
486480

487481
// prettier-ignore
488-
let httpScheme =
489-
flags.httpScheme ??
490-
(dev === true ? undefined : dev.httpScheme) ??
482+
let scheme =
483+
flags.scheme ??
484+
(dev === true ? undefined : dev.scheme) ??
491485
"http";
492486
// prettier-ignore
493-
let httpHost =
494-
flags.httpHost ??
495-
(dev === true ? undefined : dev.httpHost) ??
487+
let host =
488+
flags.host ??
489+
(dev === true ? undefined : dev.host) ??
496490
"localhost";
497491
// prettier-ignore
498-
let httpPort =
499-
flags.httpPort ??
500-
(dev === true ? undefined : dev.httpPort) ??
501-
(await findPort());
502-
// prettier-ignore
503-
let webSocketPort =
504-
flags.webSocketPort ??
505-
(dev === true ? undefined : dev.webSocketPort) ??
492+
let port =
493+
flags.port ??
494+
(dev === true ? undefined : dev.port) ??
506495
(await findPort());
507496

508497
return {
509-
httpScheme,
510-
httpHost,
511-
httpPort,
512-
webSocketPort,
498+
scheme,
499+
host,
500+
port,
513501
};
514502
};
515503

516-
type DevServeFlags = DevBuildFlags & {
504+
type DevServeFlags = DevOrigin & {
517505
command: string;
518506
restart: boolean;
519507
};
@@ -524,10 +512,7 @@ let resolveDevServe = async (
524512
let dev = config.future.unstable_dev;
525513
if (dev === false) throw Error("Cannot resolve dev options");
526514

527-
let { httpScheme, httpHost, httpPort, webSocketPort } = await resolveDevBuild(
528-
config,
529-
flags
530-
);
515+
let origin = await resolveDevOrigin(config, flags);
531516

532517
// prettier-ignore
533518
let command =
@@ -558,10 +543,7 @@ let resolveDevServe = async (
558543

559544
return {
560545
command,
561-
httpScheme,
562-
httpHost,
563-
httpPort,
564-
webSocketPort,
546+
...origin,
565547
restart,
566548
};
567549
};

0 commit comments

Comments
 (0)