Skip to content

Commit 27b186a

Browse files
authored
feat(dev): dev command defaults to remix-serve (#6177)
1 parent bebaa00 commit 27b186a

File tree

3 files changed

+98
-46
lines changed

3 files changed

+98
-46
lines changed

integration/hmr-test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ let fixture = (options: {
3535
private: true,
3636
sideEffects: false,
3737
scripts: {
38-
dev: `cross-env NODE_ENV=development node ./node_modules/@remix-run/dev/dist/cli.js dev -c "node ./server.js"`,
38+
dev: `node ./node_modules/@remix-run/dev/dist/cli.js dev -c "node ./server.js"`,
3939
},
4040
dependencies: {
4141
"@remix-run/css-bundle": "0.0.0-local-version",
@@ -245,8 +245,7 @@ test("HMR", async ({ page }) => {
245245
try {
246246
await wait(
247247
() => {
248-
let stderr = devStderr();
249-
if (stderr.length > 0) throw Error(stderr);
248+
if (dev.exitCode) throw Error("Dev server exited early");
250249
return / app ready: /.test(devStdout());
251250
},
252251
{ timeoutMs: 10_000 }

packages/remix-dev/cli/commands.ts

Lines changed: 82 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { TaskError } from "../codemod/utils/task";
2525
import { transpile as convertFileToJS } from "./useJavascript";
2626
import { warnOnce } from "../warnOnce";
2727
import type { Options } from "../compiler/options";
28+
import { getAppDependencies } from "../dependencies";
2829

2930
export async function create({
3031
appTemplate,
@@ -175,9 +176,13 @@ export async function build(
175176
sourcemap,
176177
onWarning: warnOnce,
177178
};
178-
if (config.future.unstable_dev) {
179-
let dev = await resolveDev(config.future.unstable_dev);
180-
options.devHttpOrigin = dev.httpOrigin;
179+
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+
};
181186
options.devWebsocketPort = dev.websocketPort;
182187
}
183188

@@ -237,8 +242,7 @@ export async function dev(
237242
return await new Promise(() => {});
238243
}
239244

240-
let { unstable_dev } = config.future;
241-
await devServer_unstable.serve(config, await resolveDev(unstable_dev, flags));
245+
await devServer_unstable.serve(config, await resolveDevServe(config, flags));
242246
}
243247

244248
export async function codemod(
@@ -467,49 +471,95 @@ let parseMode = (
467471

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

470-
let resolveDev = async (
471-
dev: Exclude<RemixConfig["future"]["unstable_dev"], false>,
472-
flags: {
473-
command?: string;
474-
httpScheme?: string;
475-
httpHost?: string;
476-
httpPort?: number;
477-
restart?: boolean;
478-
websocketPort?: number;
479-
} = {}
480-
): Promise<{
481-
command?: string;
482-
httpOrigin: {
483-
scheme: string;
484-
host: string;
485-
port: number;
486-
};
487-
restart: boolean;
474+
type DevBuildFlags = {
475+
httpScheme: string;
476+
httpHost: string;
477+
httpPort: number;
488478
websocketPort: number;
489-
}> => {
490-
let command = flags.command ?? (dev === true ? undefined : dev.command);
479+
};
480+
let resolveDevBuild = async (
481+
config: RemixConfig,
482+
flags: Partial<DevBuildFlags> = {}
483+
): Promise<DevBuildFlags> => {
484+
let dev = config.future.unstable_dev;
485+
if (dev === false) throw Error("This should never happen");
486+
487+
// prettier-ignore
491488
let httpScheme =
492-
flags.httpScheme ?? (dev === true ? undefined : dev.httpScheme) ?? "http";
489+
flags.httpScheme ??
490+
(dev === true ? undefined : dev.httpScheme) ??
491+
"http";
492+
// prettier-ignore
493493
let httpHost =
494-
flags.httpHost ?? (dev === true ? undefined : dev.httpHost) ?? "localhost";
494+
flags.httpHost ??
495+
(dev === true ? undefined : dev.httpHost) ??
496+
"localhost";
497+
// prettier-ignore
495498
let httpPort =
496499
flags.httpPort ??
497500
(dev === true ? undefined : dev.httpPort) ??
498501
(await findPort());
502+
// prettier-ignore
499503
let websocketPort =
500504
flags.websocketPort ??
501505
(dev === true ? undefined : dev.websocketPort) ??
502506
(await findPort());
507+
508+
return {
509+
httpScheme,
510+
httpHost,
511+
httpPort,
512+
websocketPort,
513+
};
514+
};
515+
516+
type DevServeFlags = DevBuildFlags & {
517+
command: string;
518+
restart: boolean;
519+
};
520+
let resolveDevServe = async (
521+
config: RemixConfig,
522+
flags: Partial<DevServeFlags> = {}
523+
): Promise<DevServeFlags> => {
524+
let dev = config.future.unstable_dev;
525+
if (dev === false) throw Error("Cannot resolve dev options");
526+
527+
let { httpScheme, httpHost, httpPort, websocketPort } = await resolveDevBuild(
528+
config,
529+
flags
530+
);
531+
532+
// prettier-ignore
533+
let command =
534+
flags.command ??
535+
(dev === true ? undefined : dev.command)
536+
if (!command) {
537+
command = `remix-serve ${path.relative(
538+
process.cwd(),
539+
config.serverBuildPath
540+
)}`;
541+
542+
let usingRemixAppServer =
543+
getAppDependencies(config)["@remix-run/serve"] !== undefined;
544+
if (!usingRemixAppServer) {
545+
console.error(
546+
[
547+
`Remix dev server command defaulted to '${command}', but @remix-run/serve is not installed.`,
548+
"If you are using another server, specify how to run it with `-c` or `--command` flag.",
549+
"For example, `remix dev -c 'node ./server.js'`",
550+
].join("\n")
551+
);
552+
process.exit(1);
553+
}
554+
}
503555
let restart =
504556
flags.restart ?? (dev === true ? undefined : dev.restart) ?? true;
505557

506558
return {
507559
command,
508-
httpOrigin: {
509-
scheme: httpScheme,
510-
host: httpHost,
511-
port: httpPort,
512-
},
560+
httpScheme,
561+
httpHost,
562+
httpPort,
513563
websocketPort,
514564
restart,
515565
};

packages/remix-dev/devServer_unstable/index.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,21 @@ let detectBin = async (): Promise<string> => {
4949
export let serve = async (
5050
initialConfig: RemixConfig,
5151
options: {
52-
command?: string;
53-
httpOrigin: {
54-
scheme: string;
55-
host: string;
56-
port: number;
57-
};
52+
command: string;
53+
httpScheme: string;
54+
httpHost: string;
55+
httpPort: number;
5856
websocketPort: number;
5957
restart: boolean;
6058
}
6159
) => {
6260
await loadEnv(initialConfig.rootDirectory);
6361
let websocket = Socket.serve({ port: options.websocketPort });
62+
let httpOrigin: Origin = {
63+
scheme: options.httpScheme,
64+
host: options.httpHost,
65+
port: options.httpPort,
66+
};
6467

6568
let state: {
6669
latestBuildHash?: string;
@@ -77,26 +80,26 @@ export let serve = async (
7780
env: {
7881
NODE_ENV: "development",
7982
PATH: `${bin}:${process.env.PATH}`,
80-
REMIX_DEV_HTTP_ORIGIN: stringifyOrigin(options.httpOrigin),
83+
REMIX_DEV_HTTP_ORIGIN: stringifyOrigin(httpOrigin),
8184
},
8285
});
8386
};
8487

8588
let dispose = await Compiler.watch(
8689
{
87-
config: patchPublicPath(initialConfig, options.httpOrigin),
90+
config: patchPublicPath(initialConfig, httpOrigin),
8891
options: {
8992
mode: "development",
9093
sourcemap: true,
9194
onWarning: warnOnce,
92-
devHttpOrigin: options.httpOrigin,
95+
devHttpOrigin: httpOrigin,
9396
devWebsocketPort: options.websocketPort,
9497
},
9598
},
9699
{
97100
reloadConfig: async (root) => {
98101
let config = await readConfig(root);
99-
return patchPublicPath(config, options.httpOrigin);
102+
return patchPublicPath(config, httpOrigin);
100103
},
101104
onBuildStart: (ctx) => {
102105
state.buildHashChannel?.err();
@@ -175,7 +178,7 @@ export let serve = async (
175178
}
176179
res.sendStatus(200);
177180
})
178-
.listen(options.httpOrigin.port, () => {
181+
.listen(httpOrigin.port, () => {
179182
console.log("Remix dev server ready");
180183
});
181184

0 commit comments

Comments
 (0)