From 4d2862b47e558f982a3ccbb3aad5d5f12f8ac217 Mon Sep 17 00:00:00 2001 From: Will Binns-Smith Date: Tue, 30 Aug 2022 17:01:34 -0700 Subject: [PATCH 1/2] Allow port 0 in `next dev` and `next start` Co-authored-by: Steven --- packages/next/cli/next-dev.ts | 15 +++++-------- packages/next/cli/next-start.ts | 9 ++------ packages/next/server/lib/utils.ts | 15 +++++++++++++ test/integration/cli/test/index.test.js | 28 +++++++++++++++++++++++++ test/lib/next-modes/next-dev.ts | 2 +- test/lib/next-modes/next-start.ts | 2 +- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/packages/next/cli/next-dev.ts b/packages/next/cli/next-dev.ts index 9048fd028aed..17dd7d6ee583 100755 --- a/packages/next/cli/next-dev.ts +++ b/packages/next/cli/next-dev.ts @@ -2,7 +2,7 @@ import arg from 'next/dist/compiled/arg/index.js' import { existsSync, watchFile } from 'fs' import { startServer } from '../server/lib/start-server' -import { printAndExit } from '../server/lib/utils' +import { getPort, printAndExit } from '../server/lib/utils' import * as Log from '../build/output/log' import { startedDevelopmentServer } from '../build/output' import { cliCommand } from '../lib/commands' @@ -75,16 +75,11 @@ const nextDev: cliCommand = (argv) => { ) } } - const allowRetry = !args['--port'] - let port: number = - args['--port'] || (process.env.PORT && parseInt(process.env.PORT)) || 3000 - // we allow the server to use a random port while testing - // instead of attempting to find a random port and then hope - // it doesn't become occupied before we leverage it - if (process.env.__NEXT_FORCED_PORT) { - port = parseInt(process.env.__NEXT_FORCED_PORT, 10) || 0 - } + const port = getPort(args) + // If neither --port nor PORT were specified, it's okay to retry new ports. + const allowRetry = + args['--port'] === undefined && process.env.PORT === undefined // We do not set a default host value here to prevent breaking // some set-ups that rely on listening on other interfaces diff --git a/packages/next/cli/next-start.ts b/packages/next/cli/next-start.ts index fc7cfe39369b..4f6ddf84e656 100755 --- a/packages/next/cli/next-start.ts +++ b/packages/next/cli/next-start.ts @@ -2,7 +2,7 @@ import arg from 'next/dist/compiled/arg/index.js' import { startServer } from '../server/lib/start-server' -import { printAndExit } from '../server/lib/utils' +import { getPort, printAndExit } from '../server/lib/utils' import * as Log from '../build/output/log' import isError from '../lib/is-error' import { getProjectDir } from '../lib/get-project-dir' @@ -52,13 +52,8 @@ const nextStart: cliCommand = (argv) => { } const dir = getProjectDir(args._[0]) - let port: number = - args['--port'] || (process.env.PORT && parseInt(process.env.PORT)) || 3000 const host = args['--hostname'] || '0.0.0.0' - - if (process.env.__NEXT_FORCED_PORT) { - port = parseInt(process.env.__NEXT_FORCED_PORT, 10) || 0 - } + const port = getPort(args) const keepAliveTimeoutArg: number | undefined = args['--keepAliveTimeout'] if ( diff --git a/packages/next/server/lib/utils.ts b/packages/next/server/lib/utils.ts index 578992683c8e..10f8ec20165f 100644 --- a/packages/next/server/lib/utils.ts +++ b/packages/next/server/lib/utils.ts @@ -1,3 +1,5 @@ +import type arg from 'next/dist/compiled/arg/index.js' + export function printAndExit(message: string, code = 1) { if (code === 0) { console.log(message) @@ -12,3 +14,16 @@ export function getNodeOptionsWithoutInspect() { const NODE_INSPECT_RE = /--inspect(-brk)?(=\S+)?( |$)/ return (process.env.NODE_OPTIONS || '').replace(NODE_INSPECT_RE, '') } + +export function getPort(args: arg.Result): number { + if (args['--port'] != null) { + return args['--port'] + } + + const parsed = process.env.PORT && parseInt(process.env.PORT, 10) + if (typeof parsed === 'number' && !Number.isNaN(parsed)) { + return parsed + } + + return 3000 +} diff --git a/test/integration/cli/test/index.test.js b/test/integration/cli/test/index.test.js index 6e5aeb0451fd..4d228a31f569 100644 --- a/test/integration/cli/test/index.test.js +++ b/test/integration/cli/test/index.test.js @@ -178,6 +178,34 @@ describe('CLI Usage', () => { expect(output).toMatch(new RegExp(`http://localhost:${port}`)) }) + test('--port 0', async () => { + const output = await runNextCommandDev([dir, '--port', '0'], true) + const matches = /on 0.0.0.0:(\d+)/.exec(output) + expect(matches).not.toBe(null) + + const port = parseInt(matches[1]) + // Regression test: port 0 was interpreted as if no port had been + // provided, falling back to 3000. + expect(port).not.toBe(3000) + + expect(output).toMatch(new RegExp(`http://localhost:${port}`)) + }) + + test('PORT=0', async () => { + const output = await runNextCommandDev([dir], true, { + env: { PORT: 0 }, + }) + const matches = /on 0.0.0.0:(\d+)/.exec(output) + expect(matches).not.toBe(null) + + const port = parseInt(matches[1]) + // Regression test: port 0 was interpreted as if no port had been + // provided, falling back to 3000. + expect(port).not.toBe(3000) + + expect(output).toMatch(new RegExp(`http://localhost:${port}`)) + }) + test("NODE_OPTIONS='--inspect'", async () => { // this test checks that --inspect works by launching a single debugger for the main Next.js process, // not for its subprocesses diff --git a/test/lib/next-modes/next-dev.ts b/test/lib/next-modes/next-dev.ts index f7161c7b7a9c..067d8632a08c 100644 --- a/test/lib/next-modes/next-dev.ts +++ b/test/lib/next-modes/next-dev.ts @@ -37,8 +37,8 @@ export class NextDevInstance extends NextInstance { ...process.env, ...this.env, NODE_ENV: '' as any, + PORT: this.forcedPort || '0', __NEXT_TEST_MODE: '1', - __NEXT_FORCED_PORT: this.forcedPort || '0', __NEXT_TEST_WITH_DEVTOOL: '1', }, }) diff --git a/test/lib/next-modes/next-start.ts b/test/lib/next-modes/next-start.ts index 11515fce56ed..51672583a40e 100644 --- a/test/lib/next-modes/next-start.ts +++ b/test/lib/next-modes/next-start.ts @@ -48,8 +48,8 @@ export class NextStartInstance extends NextInstance { ...process.env, ...this.env, NODE_ENV: '' as any, + PORT: this.forcedPort || '0', __NEXT_TEST_MODE: '1', - __NEXT_FORCED_PORT: this.forcedPort || '0', }, } let buildArgs = ['yarn', 'next', 'build'] From 38052713b0d41c7adb2e85ee019e57e4541c544c Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 31 Aug 2022 16:47:43 -0500 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Wyatt Johnson --- packages/next/server/lib/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/server/lib/utils.ts b/packages/next/server/lib/utils.ts index 10f8ec20165f..b149393d25ad 100644 --- a/packages/next/server/lib/utils.ts +++ b/packages/next/server/lib/utils.ts @@ -16,7 +16,7 @@ export function getNodeOptionsWithoutInspect() { } export function getPort(args: arg.Result): number { - if (args['--port'] != null) { + if (typeof args['--port'] === 'number') { return args['--port'] }