Skip to content

Commit

Permalink
feat(dev): improved networking options
Browse files Browse the repository at this point in the history
  • Loading branch information
pcattori committed Jun 29, 2023
1 parent 4ef7a88 commit debfbb9
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 94 deletions.
88 changes: 48 additions & 40 deletions packages/remix-dev/cli/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ export async function build(
sourcemap,
};
if (mode === "development" && config.future.v2_dev) {
let origin = await resolveDevOrigin(config);
options.devOrigin = origin;
let resolved = await resolveDev(config);
options.REMIX_DEV_ORIGIN = resolved.REMIX_DEV_ORIGIN;
}

let fileWatchCache = createFileWatchCache();
Expand Down Expand Up @@ -238,7 +238,8 @@ export async function dev(
return await new Promise(() => {});
}

await devServer_unstable.serve(config, await resolveDevServe(config, flags));
let resolved = await resolveDevServe(config, flags);
await devServer_unstable.serve(config, resolved);
}

export async function codemod(
Expand Down Expand Up @@ -467,58 +468,72 @@ let parseMode = (

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

type DevOrigin = {
scheme: string;
host: string;
port: number;
};
let resolveDevOrigin = async (
let resolveDev = async (
config: RemixConfig,
flags: Partial<DevOrigin> & {
flags: {
port?: number;
tlsKey?: string;
tlsCert?: string;
/** @deprecated */
scheme?: string; // TODO: remove in v2
/** @deprecated */
host?: string; // TODO: remove in v2
} = {}
): Promise<DevOrigin> => {
) => {
let dev = config.future.v2_dev;
if (dev === false) throw Error("This should never happen");

// prettier-ignore
let scheme =
flags.scheme ??
(dev === true ? undefined : dev.scheme) ??
(flags.tlsKey && flags.tlsCert) ? "https": "http";
// prettier-ignore
let host =
flags.host ??
(dev === true ? undefined : dev.host) ??
"localhost";
// prettier-ignore
let port =
flags.port ??
(dev === true ? undefined : dev.port) ??
(await findPort());

let tlsKey = flags.tlsKey ?? (dev === true ? undefined : dev.tlsKey);
if (tlsKey) tlsKey = path.resolve(tlsKey);
let tlsCert = flags.tlsCert ?? (dev === true ? undefined : dev.tlsCert);
if (tlsCert) tlsCert = path.resolve(tlsCert);
let isTLS = tlsKey && tlsCert;

let REMIX_DEV_ORIGIN = process.env.REMIX_DEV_ORIGIN;
if (REMIX_DEV_ORIGIN === undefined) {
// prettier-ignore
let scheme =
flags.scheme ?? // TODO: remove in v2
(dev === true ? undefined : dev.scheme) ?? // TODO: remove in v2
isTLS ? "https" : "http";
// prettier-ignore
let hostname =
flags.host ?? // TODO: remove in v2
(dev === true ? undefined : dev.host) ?? // TODO: remove in v2
"localhost";
REMIX_DEV_ORIGIN = `${scheme}://${hostname}:${port}`;
}

return {
scheme,
host,
port,
tlsKey,
tlsCert,
REMIX_DEV_ORIGIN: new URL(REMIX_DEV_ORIGIN),
};
};

type DevServeFlags = DevOrigin & {
command?: string;
restart: boolean;
tlsKey?: string;
tlsCert?: string;
};
let resolveDevServe = async (
config: RemixConfig,
flags: Partial<DevServeFlags> = {}
): Promise<DevServeFlags> => {
flags: {
port?: number;
tlsKey?: string;
tlsCert?: string;
scheme?: string; // TODO: remove in v2
host?: string; // TODO: remove in v2
command?: string;
restart?: boolean;
} = {}
) => {
let dev = config.future.v2_dev;
if (dev === false) throw Error("Cannot resolve dev options");

let origin = await resolveDevOrigin(config, flags);
let resolved = await resolveDev(config, flags);

// prettier-ignore
let command =
Expand All @@ -528,16 +543,9 @@ let resolveDevServe = async (
let restart =
flags.restart ?? (dev === true ? undefined : dev.restart) ?? true;

let tlsKey = flags.tlsKey ?? (dev === true ? undefined : dev.tlsKey);
if (tlsKey) tlsKey = path.resolve(tlsKey);
let tlsCert = flags.tlsCert ?? (dev === true ? undefined : dev.tlsCert);
if (tlsCert) tlsCert = path.resolve(tlsCert);

return {
...resolved,
command,
...origin,
restart,
tlsKey,
tlsCert,
};
};
8 changes: 4 additions & 4 deletions packages/remix-dev/cli/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ ${colors.logoBlue("R")} ${colors.logoGreen("E")} ${colors.logoYellow(
[v2_dev]
--command, -c Command used to run your app server
--scheme Scheme for the dev server. Default: http
--host Host for the dev server. Default: localhost
--port Port for the dev server. Default: any open port
--no-restart Do not restart the app server when rebuilds occur.
--tls-key Path to TLS key (key.pem)
Expand Down Expand Up @@ -183,13 +181,15 @@ export async function run(argv: string[] = process.argv.slice(2)) {
// dev server
"--command": String,
"-c": "--command",
"--scheme": String,
"--host": String,
"--port": Number,
"-p": "--port",
"--no-restart": Boolean,
"--tls-key": String,
"--tls-cert": String,

// deprecated, remove in v2
"--scheme": String,
"--host": String,
},
{
argv,
Expand Down
4 changes: 4 additions & 0 deletions packages/remix-dev/compiler/js/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ const createEsbuildConfig = (
publicPath: ctx.config.publicPath,
define: {
"process.env.NODE_ENV": JSON.stringify(ctx.options.mode),
"process.env.REMIX_DEV_ORIGIN": JSON.stringify(
ctx.options.REMIX_DEV_ORIGIN ?? ""
),
// TODO: remove in v2
"process.env.REMIX_DEV_SERVER_WS_PORT": JSON.stringify(
ctx.config.devServerPort
),
Expand Down
7 changes: 1 addition & 6 deletions packages/remix-dev/compiler/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,5 @@ export type Options = {
mode: Mode;
sourcemap: boolean;

// TODO: required in v2
devOrigin?: {
scheme: string;
host: string;
port: number;
};
REMIX_DEV_ORIGIN?: URL; // TODO: required in v2
};
8 changes: 6 additions & 2 deletions packages/remix-dev/compiler/server/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,16 @@ 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
// TODO: remove in v2
"process.env.REMIX_DEV_SERVER_WS_PORT": JSON.stringify(
ctx.config.devServerPort
),
"process.env.REMIX_DEV_ORIGIN": JSON.stringify(
ctx.options.REMIX_DEV_ORIGIN ?? ""
),
// TODO: remove in v2
"process.env.REMIX_DEV_HTTP_ORIGIN": JSON.stringify(
ctx.options.devOrigin ?? "" // TODO: remove nullish check in v2
ctx.options.REMIX_DEV_ORIGIN ?? ""
),
},
jsx: "automatic",
Expand Down
7 changes: 0 additions & 7 deletions packages/remix-dev/compiler/server/plugins/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,6 @@ ${Object.keys(config.routes)
export const future = ${JSON.stringify(config.future)};
export const publicPath = ${JSON.stringify(config.publicPath)};
export const entry = { module: entryServer };
${
options.devOrigin
? `export const dev = ${JSON.stringify({
port: options.devOrigin.port,
})}`
: ""
}
export const routes = {
${Object.keys(config.routes)
.map((key, index) => {
Expand Down
7 changes: 5 additions & 2 deletions packages/remix-dev/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ export type ServerPlatform = "node" | "neutral";

type Dev = {
command?: string;
scheme?: string;
host?: string;
port?: number;
restart?: boolean;
tlsKey?: string;
tlsCert?: string;

/** @deprecated remove in v2 */
scheme?: string;
/** @deprecated remove in v2 */
host?: string;
};

interface FutureConfig {
Expand Down
26 changes: 6 additions & 20 deletions packages/remix-dev/devServer_unstable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ import invariant from "../invariant";
import { logger } from "../tux";
import { kill, killtree } from "./proc";

type Origin = {
scheme: string;
host: string;
port: number;
};

let stringifyOrigin = (o: Origin) => `${o.scheme}://${o.host}:${o.port}`;

let detectBin = async (): Promise<string> => {
let pkgManager = detectPackageManager() ?? "npm";
if (pkgManager === "npm") {
Expand All @@ -47,12 +39,11 @@ export let serve = async (
initialConfig: RemixConfig,
options: {
command?: string;
scheme: string;
host: string;
port: number;
restart: boolean;
tlsKey?: string;
tlsCert?: string;
REMIX_DEV_ORIGIN: URL;
restart: boolean;
}
) => {
await loadEnv(initialConfig.rootDirectory);
Expand Down Expand Up @@ -92,12 +83,6 @@ export let serve = async (
: http.createServer(app);
let websocket = Socket.serve(server);

let origin: Origin = {
scheme: options.scheme,
host: options.host,
port: options.port,
};

let bin = await detectBin();
let startAppServer = (command?: string) => {
let cmd =
Expand All @@ -113,7 +98,8 @@ export let serve = async (
NODE_ENV: "development",
PATH:
bin + (process.platform === "win32" ? ";" : ":") + process.env.PATH,
REMIX_DEV_HTTP_ORIGIN: stringifyOrigin(origin),
REMIX_DEV_ORIGIN: options.REMIX_DEV_ORIGIN.href,
REMIX_DEV_HTTP_ORIGIN: options.REMIX_DEV_ORIGIN.href, // TODO: remove in v2
FORCE_COLOR: process.env.NO_COLOR === undefined ? "1" : "0",
},
// https://github.com/sindresorhus/execa/issues/433
Expand Down Expand Up @@ -178,7 +164,7 @@ export let serve = async (
options: {
mode: "development",
sourcemap: true,
devOrigin: origin,
REMIX_DEV_ORIGIN: options.REMIX_DEV_ORIGIN,
},
fileWatchCache,
logger,
Expand Down Expand Up @@ -276,7 +262,7 @@ export let serve = async (
}
);

server.listen(origin.port);
server.listen(options.port);

return new Promise(() => {}).finally(async () => {
state.appServer?.pid && (await kill(state.appServer.pid));
Expand Down
27 changes: 19 additions & 8 deletions packages/remix-react/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,6 @@ export const LiveReload =
process.env.NODE_ENV !== "development"
? () => null
: function LiveReload({
// TODO: remove REMIX_DEV_SERVER_WS_PORT in v2
port,
timeoutMs = 1000,
nonce = undefined,
Expand All @@ -1799,13 +1798,25 @@ export const LiveReload =
dangerouslySetInnerHTML={{
__html: js`
function remixLiveReloadConnect(config) {
let protocol = location.protocol === "https:" ? "wss:" : "ws:";
let host = location.hostname;
let port = ${port} || (window.__remixContext && window.__remixContext.dev && window.__remixContext.dev.port) || ${Number(
process.env.REMIX_DEV_SERVER_WS_PORT || 8002
)};
let socketPath = protocol + "//" + host + ":" + port + "/socket";
let ws = new WebSocket(socketPath);
let REMIX_DEV_ORIGIN = ${JSON.stringify(
process.env.REMIX_DEV_ORIGIN
)};
let protocol =
REMIX_DEV_ORIGIN ? new URL(REMIX_DEV_ORIGIN).protocol.replace(/^http/, "ws") :
location.protocol === "https:" ? "wss:" : "ws:"; // remove in v2?
let hostname = location.hostname;
let url = new URL(protocol + "//" + hostname + "/socket");
url.port =
${port} ||
REMIX_DEV_ORIGIN ? new URL(REMIX_DEV_ORIGIN).port :
Number(${
// TODO: remove in v2
process.env.REMIX_DEV_SERVER_WS_PORT
}) ||
8002;
let ws = new WebSocket(url.href);
ws.onmessage = async (message) => {
let event = JSON.parse(message.data);
if (event.type === "LOG") {
Expand Down
1 change: 0 additions & 1 deletion packages/remix-server-runtime/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export interface ServerBuild {
publicPath: string;
assetsBuildDirectory: string;
future: FutureConfig;
dev?: { port: number };
}

export interface HandleDocumentRequestFunction {
Expand Down
15 changes: 12 additions & 3 deletions packages/remix-server-runtime/dev.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import type { ServerBuild } from "./build";

export function broadcastDevReady(build: ServerBuild, origin?: string) {
export async function broadcastDevReady(build: ServerBuild, origin?: string) {
origin ??= process.env.REMIX_DEV_HTTP_ORIGIN;
if (!origin) throw Error("Dev server origin not set");
let url = new URL(origin);
url.pathname = "ping";

fetch(`${origin}/ping`, {
let response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ buildHash: build.assets.version }),
}).catch((error) => {
console.error(`Could not reach Remix dev server at ${origin}`);
console.error(`Could not reach Remix dev server at ${url}`);
throw error;
});
if (!response.ok) {
console.error(
`Could not reach Remix dev server at ${url} (${response.status})`
);
throw Error(await response.text());
}
}

export function logDevReady(build: ServerBuild) {
Expand Down
1 change: 0 additions & 1 deletion packages/remix-server-runtime/serverHandoff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export function createServerHandoffString<T>(serverHandoff: {
state: ValidateShape<T, HydrationState>;
url: string;
future: FutureConfig;
dev?: { port: 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.
Expand Down

0 comments on commit debfbb9

Please sign in to comment.