Repository: remix-run/remix
Pull request #6158 (2023-04-25 01:10:26)

fix(dev): define `process.env.REMIX_DEV_HTTP_PORT` in server build
<!--

👋 Hey, thanks for your interest in contributing to Remix!

If this is a simple docs change, go ahead and delete all this.

**Please ask first before starting work on any significant new features.**

It's never a fun experience to have your pull request declined after investing a
lot of time and effort into a new feature. To avoid this from happening, we
request that contributors create a
[Feature Request discussion](https://github.com/remix-run/remix/discussions/new?category=ideas)
to first discuss any significant new features.

https://github.com/remix-run/remix/blob/main/CONTRIBUTING.md

Please fill in or delete each item below:

-->

Closes: #

- [ ] Docs
- [ ] Tests

Testing Strategy:

<!--
Please explain how you tested this. For example:

> This test covers this code: <link to test>

Or

> I opened up my windows machine and ran this script:
>
> ```
> npx create-remix@0.0.0-experimental-7e420ee3 --template remix my-test
> cd my-test
> npm run dev
> ```
-->


changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: 846fd652f282232b169ee9dd786a3537b2f17829

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/remix-run/remix/new/pedro/define-dev-http-port-env-var?filename=.changeset/fluffy-years-invite.md&value=---%0A%22remix%22%3A%20patch%0A%22%40remix-run%2Fdev%22%3A%20patch%0A%22%40remix-run%2Freact%22%3A%20patch%0A%22%40remix-run%2Fserve%22%3A%20patch%0A%22%40remix-run%2Fserver-runtime%22%3A%20patch%0A---%0A%0Afix(dev)%3A%20define%20%60process.env.REMIX_DEV_HTTP_PORT%60%20in%20server%20build%0A)



Patch:
diff --git a/packages/remix-dev/cli/commands.ts b/packages/remix-dev/cli/commands.ts
index 6b26654a4..995c4fd7f 100644
--- a/packages/remix-dev/cli/commands.ts
+++ b/packages/remix-dev/cli/commands.ts
@@ -24,6 +24,7 @@ import { CodemodError } from "../codemod/utils/error";
 import { TaskError } from "../codemod/utils/task";
 import { transpile as convertFileToJS } from "./useJavascript";
 import { warnOnce } from "../warnOnce";
+import type { Options } from "../compiler/options";
 
 export async function create({
   appTemplate,
@@ -169,24 +170,27 @@ export async function build(
 
   let start = Date.now();
   let config = await readConfig(remixRoot);
+  let options: Options = {
+    mode,
+    sourcemap,
+    onWarning: warnOnce,
+  };
+  if (config.future.unstable_dev) {
+    let dev = await resolveDev(config.future.unstable_dev);
+    options.devHttpPort = dev.httpPort;
+    options.devWebsocketPort = dev.websocketPort;
+  }
+
   fse.emptyDirSync(config.assetsBuildDirectory);
-  await compiler
-    .build({
-      config,
-      options: {
-        mode,
-        sourcemap,
-        onWarning: warnOnce,
-      },
-    })
-    .catch((thrown) => {
-      compiler.logThrown(thrown);
-      process.exit(1);
-    });
+  await compiler.build({ config, options }).catch((thrown) => {
+    compiler.logThrown(thrown);
+    process.exit(1);
+  });
 
   console.log(`built in ${prettyMs(Date.now() - start)}`);
 }
 
+// TODO: replace watch in v2
 export async function watch(
   remixRootOrConfig: string | RemixConfig,
   modeArg?: string
@@ -232,28 +236,7 @@ export async function dev(
   }
 
   let { unstable_dev } = config.future;
-
-  let command =
-    flags.command ?? (unstable_dev === true ? undefined : unstable_dev.command);
-  let httpPort =
-    flags.httpPort ??
-    (unstable_dev === true ? undefined : unstable_dev.httpPort) ??
-    (await findPort());
-  let websocketPort =
-    flags.websocketPort ??
-    (unstable_dev === true ? undefined : unstable_dev.websocketPort) ??
-    (await findPort());
-  let restart =
-    flags.restart ??
-    (unstable_dev === true ? undefined : unstable_dev.restart) ??
-    true;
-
-  await devServer_unstable.serve(config, {
-    command,
-    httpPort,
-    websocketPort,
-    restart,
-  });
+  await devServer_unstable.serve(config, await resolveDev(unstable_dev, flags));
 }
 
 export async function codemod(
@@ -481,3 +464,37 @@ let parseMode = (
 };
 
 let findPort = async () => getPort({ port: makeRange(3001, 3100) });
+
+let resolveDev = async (
+  dev: Exclude<RemixConfig["future"]["unstable_dev"], false>,
+  flags: {
+    command?: string;
+    httpPort?: number;
+    restart?: boolean;
+    websocketPort?: number;
+  } = {}
+): Promise<{
+  command?: string;
+  httpPort: number;
+  restart: boolean;
+  websocketPort: number;
+}> => {
+  let command = flags.command ?? (dev === true ? undefined : dev.command);
+  let httpPort =
+    flags.httpPort ??
+    (dev === true ? undefined : dev.httpPort) ??
+    (await findPort());
+  let websocketPort =
+    flags.websocketPort ??
+    (dev === true ? undefined : dev.websocketPort) ??
+    (await findPort());
+  let restart =
+    flags.restart ?? (dev === true ? undefined : dev.restart) ?? true;
+
+  return {
+    command,
+    httpPort,
+    websocketPort,
+    restart,
+  };
+};
diff --git a/packages/remix-dev/compiler/options.ts b/packages/remix-dev/compiler/options.ts
index 21cb13d48..e42f1156d 100644
--- a/packages/remix-dev/compiler/options.ts
+++ b/packages/remix-dev/compiler/options.ts
@@ -2,7 +2,10 @@ type Mode = "development" | "production" | "test";
 
 export type Options = {
   mode: Mode;
-  liveReloadPort?: number;
   sourcemap: boolean;
   onWarning?: (message: string, key: string) => void;
+
+  // TODO: required in v2
+  devHttpPort?: number;
+  devWebsocketPort?: number;
 };
diff --git a/packages/remix-dev/compiler/server/compiler.ts b/packages/remix-dev/compiler/server/compiler.ts
index 60c8f69d7..cc7576d91 100644
--- a/packages/remix-dev/compiler/server/compiler.ts
+++ b/packages/remix-dev/compiler/server/compiler.ts
@@ -98,9 +98,13 @@ const createEsbuildConfig = (
     publicPath: ctx.config.publicPath,
     define: {
       "process.env.NODE_ENV": JSON.stringify(ctx.options.mode),
+      // TODO: remove REMIX_DEV_SERVER_WS_PORT in v2
       "process.env.REMIX_DEV_SERVER_WS_PORT": JSON.stringify(
         ctx.config.devServerPort
       ),
+      "process.env.REMIX_DEV_HTTP_PORT": JSON.stringify(
+        ctx.options.devHttpPort ?? ""
+      ),
     },
     jsx: "automatic",
     jsxDev: ctx.options.mode !== "production",
diff --git a/packages/remix-dev/compiler/server/plugins/entry.ts b/packages/remix-dev/compiler/server/plugins/entry.ts
index ecf4922cf..76b16114d 100644
--- a/packages/remix-dev/compiler/server/plugins/entry.ts
+++ b/packages/remix-dev/compiler/server/plugins/entry.ts
@@ -51,9 +51,9 @@ ${Object.keys(config.routes)
   export const publicPath = ${JSON.stringify(config.publicPath)};
   export const entry = { module: entryServer };
   ${
-    options.liveReloadPort
+    options.devWebsocketPort
       ? `export const dev = ${JSON.stringify({
-          liveReloadPort: options.liveReloadPort,
+          websocketPort: options.devWebsocketPort,
         })}`
       : ""
   }
diff --git a/packages/remix-dev/devServer_unstable/index.ts b/packages/remix-dev/devServer_unstable/index.ts
index c5b25013d..a117f97fe 100644
--- a/packages/remix-dev/devServer_unstable/index.ts
+++ b/packages/remix-dev/devServer_unstable/index.ts
@@ -51,9 +51,10 @@ export let serve = async (
       config,
       options: {
         mode: "development",
-        liveReloadPort: options.websocketPort, // TODO: rename liveReloadPort
         sourcemap: true,
         onWarning: warnOnce,
+        devHttpPort: options.httpPort,
+        devWebsocketPort: options.websocketPort,
       },
     },
     {
diff --git a/packages/remix-react/browser.tsx b/packages/remix-react/browser.tsx
index 5bd38fe7d..aec1fa9f0 100644
--- a/packages/remix-react/browser.tsx
+++ b/packages/remix-react/browser.tsx
@@ -23,7 +23,7 @@ declare global {
     // The number of active deferred keys rendered on the server
     a?: number;
     dev?: {
-      liveReloadPort?: number;
+      websocketPort?: number;
       hmrRuntime?: string;
     };
   };
diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx
index f844d9d6d..4c0ab2bae 100644
--- a/packages/remix-react/components.tsx
+++ b/packages/remix-react/components.tsx
@@ -1689,6 +1689,7 @@ export const LiveReload =
   process.env.NODE_ENV !== "development"
     ? () => null
     : function LiveReload({
+        // TODO: remove REMIX_DEV_SERVER_WS_PORT in v2
         port = Number(process.env.REMIX_DEV_SERVER_WS_PORT || 8002),
         timeoutMs = 1000,
         nonce = undefined,
@@ -1707,7 +1708,7 @@ export const LiveReload =
                 function remixLiveReloadConnect(config) {
                   let protocol = location.protocol === "https:" ? "wss:" : "ws:";
                   let host = location.hostname;
-                  let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.liveReloadPort) || ${String(
+                  let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.websocketPort) || ${String(
                     port
                   )};
                   let socketPath = protocol + "//" + host + ":" + port + "/socket";
diff --git a/packages/remix-react/entry.ts b/packages/remix-react/entry.ts
index 4df10fc98..fde03eca1 100644
--- a/packages/remix-react/entry.ts
+++ b/packages/remix-react/entry.ts
@@ -10,7 +10,7 @@ export interface RemixContextObject {
   serverHandoffString?: string;
   future: FutureConfig;
   abortDelay?: number;
-  dev?: { liveReloadPort: number };
+  dev?: { websocketPort: number };
 }
 
 // Additional React-Router information needed at runtime, but not hydrated
diff --git a/packages/remix-server-runtime/build.ts b/packages/remix-server-runtime/build.ts
index 0c87b7c07..4a3f666e8 100644
--- a/packages/remix-server-runtime/build.ts
+++ b/packages/remix-server-runtime/build.ts
@@ -14,7 +14,7 @@ export interface ServerBuild {
   publicPath: string;
   assetsBuildDirectory: string;
   future: FutureConfig;
-  dev?: { liveReloadPort: number };
+  dev?: { websocketPort: number };
 }
 
 export interface HandleDocumentRequestFunction {
diff --git a/packages/remix-server-runtime/serverHandoff.ts b/packages/remix-server-runtime/serverHandoff.ts
index a6165841c..edc4d4b30 100644
--- a/packages/remix-server-runtime/serverHandoff.ts
+++ b/packages/remix-server-runtime/serverHandoff.ts
@@ -20,7 +20,7 @@ export function createServerHandoffString<T>(serverHandoff: {
   // we'd end up including duplicate info
   state: ValidateShape<T, HydrationState>;
   future: FutureConfig;
-  dev?: { liveReloadPort: number };
+  dev?: { websocketPort: number };
 }): string {
   // Uses faster alternative of jsesc to escape data returned from the loaders.
   // This string is inserted directly into the HTML in the `<Scripts>` element.


Test patch:
diff --git a/packages/remix-react/__tests__/components-test.tsx b/packages/remix-react/__tests__/components-test.tsx
index d9ef31e43..b088805a4 100644
--- a/packages/remix-react/__tests__/components-test.tsx
+++ b/packages/remix-react/__tests__/components-test.tsx
@@ -47,14 +47,14 @@ describe("<LiveReload />", () => {
       LiveReload = require("../components").LiveReload;
       let { container } = render(<LiveReload />);
       expect(container.querySelector("script")).toHaveTextContent(
-        "let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.liveReloadPort) || 8002;"
+        "let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.websocketPort) || 8002;"
       );
     });
 
     it("can set the port explicitly", () => {
       let { container } = render(<LiveReload port={4321} />);
       expect(container.querySelector("script")).toHaveTextContent(
-        "let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.liveReloadPort) || 4321;"
+        "let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.websocketPort) || 4321;"
       );
     });
 
@@ -62,7 +62,7 @@ describe("<LiveReload />", () => {
       process.env.REMIX_DEV_SERVER_WS_PORT = "1234";
       let { container } = render(<LiveReload />);
       expect(container.querySelector("script")).toHaveTextContent(
-        "let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.liveReloadPort) || 1234;"
+        "let port = (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.websocketPort) || 1234;"
       );
     });