From d7d8bdf4997278aaa93d77a3ce4016be0a395491 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 28 Jan 2025 18:38:22 +0100 Subject: [PATCH 1/2] feat(dev): allow all hosts to connect to dev server for `--public` --- packages/nuxi/src/commands/dev-child.ts | 33 ++++++++++++++----------- packages/nuxi/src/commands/dev.ts | 28 ++++++++++++++------- packages/nuxi/src/utils/dev.ts | 1 + 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/packages/nuxi/src/commands/dev-child.ts b/packages/nuxi/src/commands/dev-child.ts index 51ac12c5c..bdc605d17 100644 --- a/packages/nuxi/src/commands/dev-child.ts +++ b/packages/nuxi/src/commands/dev-child.ts @@ -1,3 +1,4 @@ +import type { NuxtConfig } from '@nuxt/schema' import type { NuxtDevContext, NuxtDevIPCMessage } from '../utils/dev' import process from 'node:process' @@ -15,8 +16,7 @@ import { cwdArgs, envNameArgs, legacyRootDirArgs, logLevelArgs } from './_shared export default defineCommand({ meta: { name: '_dev', - description: - 'Run Nuxt development server (internal command to start child process)', + description: 'Run Nuxt development server (internal command to start child process)', }, args: { ...cwdArgs, @@ -26,9 +26,7 @@ export default defineCommand({ }, async run(ctx) { if (!process.send && !isTest) { - logger.warn( - '`nuxi _dev` is an internal command and should not be used directly. Please use `nuxi dev` instead.', - ) + logger.warn('`nuxi _dev` is an internal command and should not be used directly. Please use `nuxi dev` instead.') } // Prepare @@ -36,8 +34,7 @@ export default defineCommand({ const cwd = resolve(ctx.args.cwd || ctx.args.rootDir) // Get dev context info - const devContext: NuxtDevContext - = JSON.parse(process.env.__NUXT_DEV__ || 'null') || {} + const devContext: NuxtDevContext = JSON.parse(process.env.__NUXT_DEV__ || 'null') || {} // IPC Hooks function sendIPCMessage(message: T) { @@ -59,16 +56,24 @@ export default defineCommand({ process.exit() }) - const hostname = devContext.hostname - if (hostname) { - ctx.data ||= {} + const defaultOverrides: Partial = {} + + // defined hostname - allow access only from this hostname + other local hosts + if (devContext.hostname) { const protocol = devContext.proxy?.https ? 'https' : 'http' - ctx.data.overrides = defu(ctx.data.overrides, { - devServer: { cors: { origin: [`${protocol}://${hostname}`] } }, - vite: { server: { allowedHosts: [hostname] } }, - }) + defaultOverrides.devServer = { cors: { origin: [`${protocol}://${devContext.hostname}`] } } + defaultOverrides.vite = { server: { allowedHosts: [devContext.hostname] } } + } + + // explicitly public dev server - allow access from all hosts + if (devContext.public) { + defaultOverrides.devServer = { cors: { origin: '*' } } + defaultOverrides.vite = { server: { allowedHosts: true } } } + ctx.data ||= {} + ctx.data.overrides = defu(ctx.data.overrides, defaultOverrides) + // Init Nuxt dev const nuxtDev = await createNuxtDevServer({ cwd, diff --git a/packages/nuxi/src/commands/dev.ts b/packages/nuxi/src/commands/dev.ts index 1cc6051f0..b9d2d63d8 100644 --- a/packages/nuxi/src/commands/dev.ts +++ b/packages/nuxi/src/commands/dev.ts @@ -1,4 +1,4 @@ -import type { NuxtOptions } from '@nuxt/schema' +import type { NuxtConfig, NuxtOptions } from '@nuxt/schema' import type { ParsedArgs } from 'citty' import type { HTTPSOptions, ListenOptions } from 'listhen' import type { ChildProcess } from 'node:child_process' @@ -71,20 +71,29 @@ const command = defineCommand({ if (ctx.args.fork) { // Fork Nuxt dev process const devProxy = await _createDevProxy(nuxtOptions, listenOptions) - await _startSubprocess(devProxy, ctx.rawArgs, listenOptions.hostname) + await _startSubprocess(devProxy, ctx.rawArgs, listenOptions) return { listener: devProxy?.listener } } else { // Directly start Nuxt dev const { createNuxtDevServer } = await import('../utils/dev') + + const defaultOverrides: Partial = {} + + // defined hostname if (listenOptions.hostname) { - ctx.data ||= {} const protocol = listenOptions.https ? 'https' : 'http' - ctx.data.overrides = defu(ctx.data.overrides, { - devServer: { cors: { origin: [`${protocol}://${listenOptions.hostname}`] } }, - vite: { server: { allowedHosts: [listenOptions.hostname] } }, - }) + defaultOverrides.devServer = { cors: { origin: [`${protocol}://${listenOptions.hostname}`] } } + defaultOverrides.vite = { server: { allowedHosts: [listenOptions.hostname] } } } + + if (listenOptions.public) { + defaultOverrides.devServer = { cors: { origin: '*' } } + defaultOverrides.vite = { server: { allowedHosts: true } } + } + + ctx.data ||= {} + ctx.data.overrides = defu(ctx.data.overrides, defaultOverrides) const devServer = await createNuxtDevServer( { cwd, @@ -167,7 +176,7 @@ async function _createDevProxy(nuxtOptions: NuxtOptions, listenOptions: Partial< } } -async function _startSubprocess(devProxy: DevProxy, rawArgs: string[], hostname?: string) { +async function _startSubprocess(devProxy: DevProxy, rawArgs: string[], listenArgs: Partial) { let childProc: ChildProcess | undefined const kill = (signal: NodeJS.Signals | number) => { @@ -194,7 +203,8 @@ async function _startSubprocess(devProxy: DevProxy, rawArgs: string[], hostname? env: { ...process.env, __NUXT_DEV__: JSON.stringify({ - hostname, + hostname: listenArgs.hostname, + public: listenArgs.public, proxy: { url: devProxy.listener.url, urls: await devProxy.listener.getURLs(), diff --git a/packages/nuxi/src/utils/dev.ts b/packages/nuxi/src/utils/dev.ts index fe1260198..835540ac4 100644 --- a/packages/nuxi/src/utils/dev.ts +++ b/packages/nuxi/src/utils/dev.ts @@ -28,6 +28,7 @@ export type NuxtDevIPCMessage = | { type: 'nuxt:internal:dev:rejection', message: string } export interface NuxtDevContext { + public?: boolean hostname?: string proxy?: { url?: string From 9eaafc7d81521831ca8668a666cb65fcb3762248 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 28 Jan 2025 18:44:49 +0100 Subject: [PATCH 2/2] refactor: extract override logic --- packages/nuxi/src/commands/dev-child.ts | 24 ++++++------------------ packages/nuxi/src/commands/dev.ts | 19 +++---------------- packages/nuxi/src/utils/dev.ts | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/packages/nuxi/src/commands/dev-child.ts b/packages/nuxi/src/commands/dev-child.ts index bdc605d17..70d967815 100644 --- a/packages/nuxi/src/commands/dev-child.ts +++ b/packages/nuxi/src/commands/dev-child.ts @@ -1,4 +1,3 @@ -import type { NuxtConfig } from '@nuxt/schema' import type { NuxtDevContext, NuxtDevIPCMessage } from '../utils/dev' import process from 'node:process' @@ -8,7 +7,7 @@ import defu from 'defu' import { resolve } from 'pathe' import { isTest } from 'std-env' -import { createNuxtDevServer } from '../utils/dev' +import { _getDevServerOverrides, createNuxtDevServer } from '../utils/dev' import { overrideEnv } from '../utils/env' import { logger } from '../utils/logger' import { cwdArgs, envNameArgs, legacyRootDirArgs, logLevelArgs } from './_shared' @@ -56,23 +55,12 @@ export default defineCommand({ process.exit() }) - const defaultOverrides: Partial = {} - - // defined hostname - allow access only from this hostname + other local hosts - if (devContext.hostname) { - const protocol = devContext.proxy?.https ? 'https' : 'http' - defaultOverrides.devServer = { cors: { origin: [`${protocol}://${devContext.hostname}`] } } - defaultOverrides.vite = { server: { allowedHosts: [devContext.hostname] } } - } - - // explicitly public dev server - allow access from all hosts - if (devContext.public) { - defaultOverrides.devServer = { cors: { origin: '*' } } - defaultOverrides.vite = { server: { allowedHosts: true } } - } - ctx.data ||= {} - ctx.data.overrides = defu(ctx.data.overrides, defaultOverrides) + ctx.data.overrides = defu(ctx.data.overrides, _getDevServerOverrides({ + hostname: devContext.hostname, + public: devContext.public, + https: devContext.proxy?.https, + })) // Init Nuxt dev const nuxtDev = await createNuxtDevServer({ diff --git a/packages/nuxi/src/commands/dev.ts b/packages/nuxi/src/commands/dev.ts index b9d2d63d8..64d42e5cc 100644 --- a/packages/nuxi/src/commands/dev.ts +++ b/packages/nuxi/src/commands/dev.ts @@ -1,4 +1,4 @@ -import type { NuxtConfig, NuxtOptions } from '@nuxt/schema' +import type { NuxtOptions } from '@nuxt/schema' import type { ParsedArgs } from 'citty' import type { HTTPSOptions, ListenOptions } from 'listhen' import type { ChildProcess } from 'node:child_process' @@ -17,6 +17,7 @@ import { resolve } from 'pathe' import { isBun, isTest } from 'std-env' import { showVersions } from '../utils/banner' +import { _getDevServerOverrides } from '../utils/dev' import { overrideEnv } from '../utils/env' import { loadKit } from '../utils/kit' import { logger } from '../utils/logger' @@ -78,22 +79,8 @@ const command = defineCommand({ // Directly start Nuxt dev const { createNuxtDevServer } = await import('../utils/dev') - const defaultOverrides: Partial = {} - - // defined hostname - if (listenOptions.hostname) { - const protocol = listenOptions.https ? 'https' : 'http' - defaultOverrides.devServer = { cors: { origin: [`${protocol}://${listenOptions.hostname}`] } } - defaultOverrides.vite = { server: { allowedHosts: [listenOptions.hostname] } } - } - - if (listenOptions.public) { - defaultOverrides.devServer = { cors: { origin: '*' } } - defaultOverrides.vite = { server: { allowedHosts: true } } - } - ctx.data ||= {} - ctx.data.overrides = defu(ctx.data.overrides, defaultOverrides) + ctx.data.overrides = defu(ctx.data.overrides, _getDevServerOverrides(listenOptions)) const devServer = await createNuxtDevServer( { cwd, diff --git a/packages/nuxi/src/utils/dev.ts b/packages/nuxi/src/utils/dev.ts index 835540ac4..8f56faa88 100644 --- a/packages/nuxi/src/utils/dev.ts +++ b/packages/nuxi/src/utils/dev.ts @@ -340,3 +340,21 @@ function _getAddressURL(addr: AddressInfo, https: boolean) { const port = addr.port || 3000 return `${proto}://${host}:${port}/` } + +export function _getDevServerOverrides(listenOptions: Partial>) { + const defaultOverrides: Partial = {} + + // defined hostname + if (listenOptions.hostname) { + const protocol = listenOptions.https ? 'https' : 'http' + defaultOverrides.devServer = { cors: { origin: [`${protocol}://${listenOptions.hostname}`] } } + defaultOverrides.vite = { server: { allowedHosts: [listenOptions.hostname] } } + } + + if (listenOptions.public) { + defaultOverrides.devServer = { cors: { origin: '*' } } + defaultOverrides.vite = { server: { allowedHosts: true } } + } + + return defaultOverrides +}