From 38b089e48b0692d564386d7cbdfdf7769b2d4703 Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Sat, 2 Sep 2023 18:56:21 +0700 Subject: [PATCH 1/7] fix start-server --- package.json | 2 +- packages/next/src/server/lib/start-server.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index efbaec07b4229..4b0957c7c70ab 100644 --- a/package.json +++ b/package.json @@ -247,7 +247,7 @@ }, "engines": { "node": ">=16.14.0", - "pnpm": "8.6.11" + "pnpm": ">=8.6.11" }, "packageManager": "pnpm@8.6.11" } diff --git a/packages/next/src/server/lib/start-server.ts b/packages/next/src/server/lib/start-server.ts index 661bcd8701842..327a74bb813a9 100644 --- a/packages/next/src/server/lib/start-server.ts +++ b/packages/next/src/server/lib/start-server.ts @@ -194,11 +194,11 @@ export async function startServer({ ) const formattedHostname = - !hostname || hostname === '0.0.0.0' - ? 'localhost' - : actualHostname === '[::]' + !hostname || actualHostname === '0.0.0.0' + ? 'localhost' + : actualHostname === '[::]' ? '[::1]' - : actualHostname + : formatHostname(hostname) port = typeof addr === 'object' ? addr?.port || port : port const appUrl = `${ From 74226ce2602353729db12304156dfd0cc3fa18fc Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Sat, 2 Sep 2023 22:28:26 +0700 Subject: [PATCH 2/7] done fix --- .../05-next-config-js/output.mdx | 3 ++- .../docker/development/Dockerfile | 4 +++- .../docker/production/Dockerfile | 4 +++- .../docker/staging/Dockerfile | 4 +++- examples/with-docker/Dockerfile | 5 ++-- .../next/src/experimental/testmode/server.ts | 4 ++-- .../next/src/server/lib/format-hostname.ts | 1 - .../next/src/server/lib/get-fetch-hostname.ts | 19 +++++++++++++++ packages/next/src/server/lib/render-server.ts | 7 ++---- .../src/server/lib/setup-server-worker.ts | 3 +-- packages/next/src/server/lib/start-server.ts | 24 +++++++++---------- packages/next/src/server/next.ts | 2 +- 12 files changed, 51 insertions(+), 29 deletions(-) create mode 100644 packages/next/src/server/lib/get-fetch-hostname.ts diff --git a/docs/02-app/02-api-reference/05-next-config-js/output.mdx b/docs/02-app/02-api-reference/05-next-config-js/output.mdx index 4d57da48a679f..01322ec942cf9 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/output.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/output.mdx @@ -39,8 +39,8 @@ Additionally, a minimal `server.js` file is also output which can be used instea > **Good to know**: > +> - If your project needs to listen to a specific port or hostname, you can define `PORT` or `HOSTNAME` environment variables before running `server.js`. For example, run `PORT=8080 HOSTNAME=0.0.0.0 node server.js` to start the server on `http://0.0.0.0:8080`. > - If your project uses [Image Optimization](/docs/app/building-your-application/optimizing/images) with the default `loader`, you must install `sharp` as a dependency: -> - If your project needs alternative port or hostname for listening, you can define `PORT` and `HOSTNAME` environment variables, before running `server.js`. For example, `PORT=3000 HOSTNAME=localhost node server.js`. @@ -49,6 +49,7 @@ Additionally, a minimal `server.js` file is also output which can be used instea > **Good to know**: > > - `next.config.js` is read during `next build` and serialized into the `server.js` output file. If the legacy [`serverRuntimeConfig` or `publicRuntimeConfig` options](/docs/pages/api-reference/next-config-js/runtime-configuration) are being used, the values will be specific to values at build time. +> - If your project needs to listen to a specific port or hostname, you can define `PORT` or `HOSTNAME` environment variables before running `server.js`. For example, run `PORT=8080 HOSTNAME=0.0.0.0 node server.js` to start the server on `http://0.0.0.0:8080`. > - If your project uses [Image Optimization](/docs/pages/building-your-application/optimizing/images) with the default `loader`, you must install `sharp` as a dependency: diff --git a/examples/with-docker-multi-env/docker/development/Dockerfile b/examples/with-docker-multi-env/docker/development/Dockerfile index 5627577363b6c..5aab333a403d2 100644 --- a/examples/with-docker-multi-env/docker/development/Dockerfile +++ b/examples/with-docker-multi-env/docker/development/Dockerfile @@ -47,6 +47,8 @@ USER nextjs EXPOSE 3000 ENV PORT 3000 -ENV HOSTNAME localhost +# Uncomment the following line if `process.env.HOSTNAME` is not provided by your provider +# and `localhost` doesn't work with your use case. +# ENV HOSTNAME 0.0.0.0 CMD ["node", "server.js"] diff --git a/examples/with-docker-multi-env/docker/production/Dockerfile b/examples/with-docker-multi-env/docker/production/Dockerfile index b6892e9c0ab10..19a50760def9a 100644 --- a/examples/with-docker-multi-env/docker/production/Dockerfile +++ b/examples/with-docker-multi-env/docker/production/Dockerfile @@ -48,6 +48,8 @@ USER nextjs EXPOSE 3000 ENV PORT 3000 -ENV HOSTNAME localhost +# Uncomment the following line if `process.env.HOSTNAME` is not provided by your provider +# and `localhost` doesn't work with your use case. +# ENV HOSTNAME 0.0.0.0 CMD ["node", "server.js"] diff --git a/examples/with-docker-multi-env/docker/staging/Dockerfile b/examples/with-docker-multi-env/docker/staging/Dockerfile index 14b3ae0c78afd..442ed1788a5b9 100644 --- a/examples/with-docker-multi-env/docker/staging/Dockerfile +++ b/examples/with-docker-multi-env/docker/staging/Dockerfile @@ -48,6 +48,8 @@ USER nextjs EXPOSE 3000 ENV PORT 3000 -ENV HOSTNAME localhost +# Uncomment the following line if `process.env.HOSTNAME` is not provided by your provider +# and `localhost` doesn't work with your use case. +# ENV HOSTNAME 0.0.0.0 CMD ["node", "server.js"] diff --git a/examples/with-docker/Dockerfile b/examples/with-docker/Dockerfile index 28514819179b9..ed0c36d56c95b 100644 --- a/examples/with-docker/Dockerfile +++ b/examples/with-docker/Dockerfile @@ -59,7 +59,8 @@ USER nextjs EXPOSE 3000 ENV PORT 3000 -# set hostname to localhost -ENV HOSTNAME "0.0.0.0" +# Uncomment the following line if `process.env.HOSTNAME` is not provided by your provider +# and `localhost` doesn't work with your use case. +# ENV HOSTNAME 0.0.0.0 CMD ["node", "server.js"] diff --git a/packages/next/src/experimental/testmode/server.ts b/packages/next/src/experimental/testmode/server.ts index ff889a5b80f15..45f1c6b789536 100644 --- a/packages/next/src/experimental/testmode/server.ts +++ b/packages/next/src/experimental/testmode/server.ts @@ -5,8 +5,8 @@ import type { ProxyResponse, } from './proxy' import { ClientRequestInterceptor } from 'next/dist/compiled/@mswjs/interceptors/ClientRequest' -import { WorkerRequestHandler } from '../../server/lib/setup-server-worker' -import { NodeRequestHandler } from '../../server/next-server' +import type { WorkerRequestHandler } from '../../server/lib/setup-server-worker' +import type { NodeRequestHandler } from '../../server/next-server' interface TestReqInfo { url: string diff --git a/packages/next/src/server/lib/format-hostname.ts b/packages/next/src/server/lib/format-hostname.ts index 222146a5a9dd4..b44506e66bbee 100644 --- a/packages/next/src/server/lib/format-hostname.ts +++ b/packages/next/src/server/lib/format-hostname.ts @@ -6,7 +6,6 @@ import { isIPv6 } from './is-ipv6' * @param hostname * @returns */ - export function formatHostname(hostname: string): string { return isIPv6(hostname) ? `[${hostname}]` : hostname } diff --git a/packages/next/src/server/lib/get-fetch-hostname.ts b/packages/next/src/server/lib/get-fetch-hostname.ts new file mode 100644 index 0000000000000..d36e045fa8e54 --- /dev/null +++ b/packages/next/src/server/lib/get-fetch-hostname.ts @@ -0,0 +1,19 @@ +import { formatHostname } from './format-hostname' + +/** + * Gets the hostname used to fetch pages (also checks whether the server + * is running on `0.0.0.0` or `::`). + * @param actualHostname - The host the server runs on. + * @param providedHostname - The hostname the user provides. + * @returns + */ +export function getFetchHostname( + actualHostname: string, + providedHostname: string | undefined +) { + return actualHostname === '0.0.0.0' + ? 'localhost' + : actualHostname === '::' + ? '[::1]' + : formatHostname(providedHostname || actualHostname) +} diff --git a/packages/next/src/server/lib/render-server.ts b/packages/next/src/server/lib/render-server.ts index 9c2eee1fd2086..0befdf5316bc7 100644 --- a/packages/next/src/server/lib/render-server.ts +++ b/packages/next/src/server/lib/render-server.ts @@ -2,9 +2,9 @@ import type { RequestHandler } from '../next' // this must come first as it includes require hooks import { initializeServerWorker } from './setup-server-worker' -import { formatHostname } from './format-hostname' import next from '../next' import { PropagateToWorkersField } from './router-utils/types' +import { getFetchHostname } from './get-fetch-hostname' export const WORKER_SELF_EXIT_CODE = 77 @@ -102,11 +102,8 @@ export async function initialize(opts: { ...opts, _routerWorker: opts.workerType === 'router', _renderWorker: opts.workerType === 'render', - hostname, customServer: false, httpServer: server, - port: opts.port, - isNodeDebugging: opts.isNodeDebugging, }) requestHandler = app.getRequestHandler() @@ -115,7 +112,7 @@ export async function initialize(opts: { result = { port, - hostname: formatHostname(hostname), + hostname: getFetchHostname(hostname, opts.hostname), } return result diff --git a/packages/next/src/server/lib/setup-server-worker.ts b/packages/next/src/server/lib/setup-server-worker.ts index ba7d195fa4ff2..ae0f4befad84b 100644 --- a/packages/next/src/server/lib/setup-server-worker.ts +++ b/packages/next/src/server/lib/setup-server-worker.ts @@ -87,7 +87,6 @@ export async function initializeServerWorker( upgradeHandler(req, socket, upgrade) }) } - let hostname = opts.hostname || 'localhost' server.on('listening', async () => { try { @@ -116,6 +115,6 @@ export async function initializeServerWorker( return reject(err) } }) - server.listen(0, hostname) + server.listen(0, opts.hostname) }) } diff --git a/packages/next/src/server/lib/start-server.ts b/packages/next/src/server/lib/start-server.ts index 327a74bb813a9..98ce29a520c9c 100644 --- a/packages/next/src/server/lib/start-server.ts +++ b/packages/next/src/server/lib/start-server.ts @@ -11,11 +11,12 @@ import { getDebugPort } from './utils' import { formatHostname } from './format-hostname' import { initialize } from './router-server' import fs from 'fs' -import { +import type { WorkerRequestHandler, WorkerUpgradeHandler, } from './setup-server-worker' import { checkIsNodeDebugging } from './is-node-debugging' +import { getFetchHostname } from './get-fetch-hostname' const debug = setupDebug('next:start-server') if (process.env.NEXT_CPU_PROF) { @@ -28,7 +29,7 @@ export interface StartServerOptions { port: number logReady?: boolean isDev: boolean - hostname: string + hostname?: string allowRetry?: boolean customServer?: boolean minimalMode?: boolean @@ -54,7 +55,7 @@ export async function getRequestHandlers({ dir: string port: number isDev: boolean - hostname: string + hostname?: string minimalMode?: boolean isNodeDebugging?: boolean keepAliveTimeout?: number @@ -187,18 +188,15 @@ export async function startServer({ await new Promise((resolve) => { server.on('listening', async () => { const addr = server.address() - const actualHostname = formatHostname( + const host = typeof addr === 'object' ? addr?.address || hostname || 'localhost' : addr - ) - const formattedHostname = - !hostname || actualHostname === '0.0.0.0' - ? 'localhost' - : actualHostname === '[::]' - ? '[::1]' - : formatHostname(hostname) + // The server's actual host + const formattedServerHost = formatHostname(host) + // appUrl's host - the server should respond when this hostname is fetched + const formattedHostname = getFetchHostname(host, hostname) port = typeof addr === 'object' ? addr?.port || port : port const appUrl = `${ @@ -215,7 +213,9 @@ export async function startServer({ } if (logReady) { - Log.ready(`started server on ${actualHostname}:${port}, url: ${appUrl}`) + Log.ready( + `started server on ${formattedServerHost}:${port}, url: ${appUrl}` + ) // expose the main port to render workers process.env.PORT = port + '' } diff --git a/packages/next/src/server/next.ts b/packages/next/src/server/next.ts index 6cdd4282007b9..18a2d0a174487 100644 --- a/packages/next/src/server/next.ts +++ b/packages/next/src/server/next.ts @@ -19,7 +19,7 @@ import { PHASE_PRODUCTION_SERVER } from '../shared/lib/constants' import { getTracer } from './lib/trace/tracer' import { NextServerSpan } from './lib/trace/constants' import { formatUrl } from '../shared/lib/router/utils/format-url' -import { +import type { WorkerRequestHandler, WorkerUpgradeHandler, } from './lib/setup-server-worker' From 456842958835dd0b9a2b8bb1dea40bd3dfa29c3d Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Sat, 2 Sep 2023 23:40:19 +0700 Subject: [PATCH 3/7] fix middleware crashing --- packages/next/src/server/next-server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index eef8514491d82..501ebc9ce9982 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -1426,7 +1426,7 @@ export default class NextNodeServer extends BaseServer { const locale = params.parsed.query.__nextLocale url = `${getRequestMeta(params.request, '_protocol')}://${ - this.fetchHostname + this.fetchHostname || 'localhost' }:${this.port}${locale ? `/${locale}` : ''}${params.parsed.pathname}${ query ? `?${query}` : '' }` From d30be67d661163019f2262c6a256fa67c9350dab Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Sat, 2 Sep 2023 23:57:57 +0700 Subject: [PATCH 4/7] fix test --- packages/next/src/server/lib/get-fetch-hostname.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/server/lib/get-fetch-hostname.ts b/packages/next/src/server/lib/get-fetch-hostname.ts index d36e045fa8e54..800b6e8940521 100644 --- a/packages/next/src/server/lib/get-fetch-hostname.ts +++ b/packages/next/src/server/lib/get-fetch-hostname.ts @@ -11,9 +11,9 @@ export function getFetchHostname( actualHostname: string, providedHostname: string | undefined ) { - return actualHostname === '0.0.0.0' + return !providedHostname || actualHostname === '0.0.0.0' ? 'localhost' : actualHostname === '::' ? '[::1]' - : formatHostname(providedHostname || actualHostname) + : formatHostname(providedHostname) } From 53fc4bc865653edf8c687a1b8ab447695a72d775 Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Sun, 3 Sep 2023 00:11:11 +0700 Subject: [PATCH 5/7] provide default --- packages/next/src/server/lib/render-server.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/next/src/server/lib/render-server.ts b/packages/next/src/server/lib/render-server.ts index 0befdf5316bc7..d38a9de60c94b 100644 --- a/packages/next/src/server/lib/render-server.ts +++ b/packages/next/src/server/lib/render-server.ts @@ -88,6 +88,8 @@ export async function initialize(opts: { let requestHandler: RequestHandler let upgradeHandler: any + const optsHostname = opts.hostname || 'localhost' + const { port, server, hostname } = await initializeServerWorker( (...args) => { return requestHandler(...args) @@ -95,13 +97,17 @@ export async function initialize(opts: { (...args) => { return upgradeHandler(...args) }, - opts + { + ...opts, + hostname: optsHostname, + } ) app = next({ ...opts, _routerWorker: opts.workerType === 'router', _renderWorker: opts.workerType === 'render', + hostname: optsHostname, customServer: false, httpServer: server, }) @@ -112,7 +118,7 @@ export async function initialize(opts: { result = { port, - hostname: getFetchHostname(hostname, opts.hostname), + hostname: getFetchHostname(hostname, optsHostname), } return result From f767b48ddaf30e6566cf2bc827884481c072da64 Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Tue, 5 Sep 2023 21:59:59 +0700 Subject: [PATCH 6/7] clean up merge --- packages/next/src/lib/turbopack-warning.ts | 28 ++++++++------------ packages/next/src/server/lib/start-server.ts | 7 ++--- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/packages/next/src/lib/turbopack-warning.ts b/packages/next/src/lib/turbopack-warning.ts index 51f6179b5e042..2eb7f72f3237b 100644 --- a/packages/next/src/lib/turbopack-warning.ts +++ b/packages/next/src/lib/turbopack-warning.ts @@ -95,13 +95,11 @@ export async function validateTurboNextConfig({ let thankYouMessage = [ - `Thank you for trying Next.js v13 with Turbopack! As a reminder`, - `Turbopack is currently in beta and not yet ready for production.`, - `We appreciate your ongoing support as we work to make it ready`, - `for everyone.`, - ] - .map((line) => `${line}`) - .join('\n') + '\n\n' + 'Thank you for trying Next.js v13 with Turbopack! As a reminder', + 'Turbopack is currently in beta and not yet ready for production.', + 'We appreciate your ongoing support as we work to make it ready', + 'for everyone.', + ].join('\n') + '\n\n' let unsupportedParts = '' let babelrc = await getBabelConfigFile(dir) @@ -205,36 +203,32 @@ export async function validateTurboNextConfig({ `\n${chalk.yellow( 'Warning:' )} Webpack is configured while Turbopack is not, which may cause problems.\n - ${`See instructions if you need to configure Turbopack:\n https://turbo.build/pack/docs/features/customizing-turbopack\n`}` +See instructions if you need to configure Turbopack:\n https://turbo.build/pack/docs/features/customizing-turbopack\n` ) } if (babelrc) { unsupportedParts += `\n- Babel detected (${chalk.cyan( babelrc - )})\n ${`Babel is not yet supported. To use Turbopack at the moment,\n you'll need to remove your usage of Babel.`}` + )})\n Babel is not yet supported. To use Turbopack at the moment,\n you'll need to remove your usage of Babel.` } if (unsupportedConfig.length) { unsupportedParts += `\n\n- Unsupported Next.js configuration option(s) (${chalk.cyan( 'next.config.js' - )})\n ${`To use Turbopack, remove the following configuration options:\n${unsupportedConfig + )})\n To use Turbopack, remove the following configuration options:\n${unsupportedConfig .map((name) => ` - ${chalk.red(name)}\n`) - .join('')} `} ` + .join('')}` } if (unsupportedParts && !isCustomTurbopack) { const pkgManager = getPkgManager(dir) console.error( - `${'Error:'} You are using configuration and/or tools that are not yet\nsupported by Next.js v13 with Turbopack:\n${unsupportedParts}\n + `Error: You are using configuration and/or tools that are not yet\nsupported by Next.js v13 with Turbopack:\n${unsupportedParts}\n If you cannot make the changes above, but still want to try out\nNext.js v13 with Turbopack, create the Next.js v13 playground app\nby running the following commands: ${chalk.bold.cyan( - `${ - pkgManager === 'npm' - ? 'npx create-next-app' - : `${pkgManager} create next-app` - } --example with-turbopack with-turbopack-app` + `${pkgManager} create next-app --example with-turbopack with-turbopack-app` )}\n cd with-turbopack-app\n ${pkgManager} run dev ` ) diff --git a/packages/next/src/server/lib/start-server.ts b/packages/next/src/server/lib/start-server.ts index 69eb04388a206..352b6e1b1dccf 100644 --- a/packages/next/src/server/lib/start-server.ts +++ b/packages/next/src/server/lib/start-server.ts @@ -9,6 +9,7 @@ import * as Log from '../../build/output/log' import setupDebug from 'next/dist/compiled/debug' import { getDebugPort } from './utils' import { formatHostname } from './format-hostname' +import { getFetchHostname } from './get-fetch-hostname' import { initialize } from './router-server' import fs from 'fs' import type { @@ -230,11 +231,7 @@ export async function startServer({ ) Log.bootstrap(` - Local: ${appUrl}`) if (hostname) { - Log.bootstrap( - ` - Network: ${actualHostname}${ - (port + '').startsWith(':') ? '' : ':' - }${port}` - ) + Log.bootstrap(` - Network: ${formattedServerHost}:${port}`) } if (envInfo?.length) Log.bootstrap(` - Environments: ${envInfo.join(', ')}`) From 060c3e2d512e78afd3ea3e217453c342cee7f1b3 Mon Sep 17 00:00:00 2001 From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com> Date: Tue, 5 Sep 2023 22:12:21 +0700 Subject: [PATCH 7/7] chore: code clean up [skip ci] --- packages/next/src/server/lib/render-server.ts | 15 ++++++++------- .../next/src/server/lib/setup-server-worker.ts | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/next/src/server/lib/render-server.ts b/packages/next/src/server/lib/render-server.ts index d38a9de60c94b..42f73cf07fe40 100644 --- a/packages/next/src/server/lib/render-server.ts +++ b/packages/next/src/server/lib/render-server.ts @@ -88,7 +88,11 @@ export async function initialize(opts: { let requestHandler: RequestHandler let upgradeHandler: any - const optsHostname = opts.hostname || 'localhost' + const providedHost = opts.hostname || 'localhost' + const serverWorkerOpts = { + ...opts, + hostname: providedHost, + } const { port, server, hostname } = await initializeServerWorker( (...args) => { @@ -97,17 +101,14 @@ export async function initialize(opts: { (...args) => { return upgradeHandler(...args) }, - { - ...opts, - hostname: optsHostname, - } + serverWorkerOpts ) app = next({ ...opts, _routerWorker: opts.workerType === 'router', _renderWorker: opts.workerType === 'render', - hostname: optsHostname, + hostname: providedHost, customServer: false, httpServer: server, }) @@ -118,7 +119,7 @@ export async function initialize(opts: { result = { port, - hostname: getFetchHostname(hostname, optsHostname), + hostname: getFetchHostname(hostname, providedHost), } return result diff --git a/packages/next/src/server/lib/setup-server-worker.ts b/packages/next/src/server/lib/setup-server-worker.ts index ae0f4befad84b..68f85d932dce7 100644 --- a/packages/next/src/server/lib/setup-server-worker.ts +++ b/packages/next/src/server/lib/setup-server-worker.ts @@ -41,7 +41,7 @@ export async function initializeServerWorker( port: number dev: boolean minimalMode?: boolean - hostname?: string + hostname: string workerType: 'router' | 'render' isNodeDebugging: boolean keepAliveTimeout?: number