From de0175b1b236e3dc02150f6e855923c2711b0548 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 11:46:21 +0200 Subject: [PATCH 01/11] fix(dev): expose port/host to `options.devServer` --- packages/nuxi/src/commands/dev.ts | 1 + packages/nuxi/src/dev/socket.ts | 6 +---- packages/nuxi/src/dev/utils.ts | 10 +++++-- packages/nuxt-cli/test/e2e/dev.spec.ts | 26 +++++++++++++++++++ .../dev/modules/log-dev-server-options.ts | 18 +++++++++++++ .../nuxt-cli/test/fixtures/dev/package.json | 12 +++++++++ pnpm-lock.yaml | 6 +++++ pnpm-workspace.yaml | 1 + 8 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 packages/nuxt-cli/test/e2e/dev.spec.ts create mode 100644 packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts create mode 100644 packages/nuxt-cli/test/fixtures/dev/package.json diff --git a/packages/nuxi/src/commands/dev.ts b/packages/nuxi/src/commands/dev.ts index 5d5445b5d..86413b569 100644 --- a/packages/nuxi/src/commands/dev.ts +++ b/packages/nuxi/src/commands/dev.ts @@ -149,6 +149,7 @@ const command = defineCommand({ url: devProxy.listener.url, urls, https: devProxy.listener.https, + addr: devProxy.listener.address, }, // if running with nuxt v4 or `NUXT_SOCKET=1`, we use the socket listener // otherwise pass 'true' to listen on a random port instead diff --git a/packages/nuxi/src/dev/socket.ts b/packages/nuxi/src/dev/socket.ts index 400a4bc04..d87565346 100644 --- a/packages/nuxi/src/dev/socket.ts +++ b/packages/nuxi/src/dev/socket.ts @@ -59,11 +59,7 @@ export async function createSocketListener(handler: RequestListener, ssl = false const url = formatSocketURL(socketPath, ssl) return { url, - address: { - socketPath, - address: 'localhost', - port: 3000, - }, + address: { socketPath }, async close() { try { server.removeAllListeners() diff --git a/packages/nuxi/src/dev/utils.ts b/packages/nuxi/src/dev/utils.ts index edc360cdf..49db232c3 100644 --- a/packages/nuxi/src/dev/utils.ts +++ b/packages/nuxi/src/dev/utils.ts @@ -55,6 +55,7 @@ export interface NuxtDevContext { url?: string urls?: ListenURL[] https?: boolean | HTTPSOptions + addr?: AddressInfo } } @@ -125,7 +126,7 @@ export class NuxtDevServer extends EventEmitter { handler: RequestListener listener: Pick & { _url?: string - address: { socketPath: string, port: number, address: string } | AddressInfo + address: { socketPath: string } | AddressInfo } constructor(private options: NuxtDevServerOptions) { @@ -313,7 +314,12 @@ export class NuxtDevServer extends EventEmitter { // Sync internal server info to the internals // It is important for vite-node to use the internal URL but public proto - const addr = this.listener.address + const addr = { + port: 3000, + address: 'localhost', + ...this.options.devContext.proxy?.addr, + ...this.listener.address, + } this._currentNuxt.options.devServer.host = addr.address this._currentNuxt.options.devServer.port = addr.port this._currentNuxt.options.devServer.url = 'socketPath' in addr diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts new file mode 100644 index 000000000..82575e73a --- /dev/null +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -0,0 +1,26 @@ +import { readFile } from 'node:fs/promises' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { getPort } from 'get-port-please' +import { x } from 'tinyexec' +import { describe, expect, it } from 'vitest' + +const fixtureDir = fileURLToPath(new URL('../fixtures/dev', import.meta.url)) + +describe('dev server', () => { + it('should expose dev server address to nuxt options', { timeout: 50_000 }, async () => { + const host = '127.0.0.1' + const port = await getPort({ host, port: 3031 }) + await x('nuxt', ['dev', `--host=${host}`, `--port=${port}`], { + nodeOptions: { cwd: fixtureDir }, + throwOnError: true, + }) + const options = await readFile(join(fixtureDir, '.nuxt', 'dev-server.json'), 'utf-8').then(JSON.parse) + expect(options).toMatchObject({ + https: false, + host, + port, + url: `http://${host}:${port}/`, + }) + }) +}) diff --git a/packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts b/packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts new file mode 100644 index 000000000..929a30866 --- /dev/null +++ b/packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts @@ -0,0 +1,18 @@ +import { writeFile } from 'node:fs/promises' +import process from 'node:process' +import { defineNuxtModule, useNuxt } from 'nuxt/kit' + +export default defineNuxtModule({ + meta: { + name: 'nuxt-cli-test-module', + }, + setup() { + const nuxt = useNuxt() + + nuxt.hook('build:before', async () => { + await writeFile('.nuxt/dev-server.json', JSON.stringify(nuxt.options.devServer)) + await nuxt.close() + process.exit(0) + }) + }, +}) diff --git a/packages/nuxt-cli/test/fixtures/dev/package.json b/packages/nuxt-cli/test/fixtures/dev/package.json new file mode 100644 index 000000000..42fa2e37c --- /dev/null +++ b/packages/nuxt-cli/test/fixtures/dev/package.json @@ -0,0 +1,12 @@ +{ + "name": "fixtures-dev", + "version": "1.0.0", + "private": true, + "scripts": { + "dev:prepare": "nuxt prepare", + "test": "vitest" + }, + "dependencies": { + "nuxt": "^4.0.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8a594a868..910cc4e29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -322,6 +322,12 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.3)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0) + packages/nuxt-cli/test/fixtures/dev: + dependencies: + nuxt: + specifier: ^4.0.0 + version: 4.0.0(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@22.16.3)(@vue/compiler-sfc@3.5.17)(db0@0.3.2)(eslint@9.31.0(jiti@2.4.2))(ioredis@5.6.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.45.0)(terser@5.43.1)(typescript@5.8.3)(vite@7.0.4(@types/node@22.16.3)(jiti@2.4.2)(terser@5.43.1)(yaml@2.8.0))(yaml@2.8.0) + playground: dependencies: nuxt: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0e90cf81d..11881ced9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - packages/* + - packages/nuxt-cli/test/fixtures/* - playground From 0b6c5a03e5d9787a4bf37ea24ec877da08c832a0 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 11:54:50 +0200 Subject: [PATCH 02/11] test: simplify test with `runCommand` --- packages/nuxt-cli/package.json | 1 + packages/nuxt-cli/test/e2e/dev.spec.ts | 13 ++++++++----- .../{dev/modules => }/log-dev-server-options.ts | 7 +++---- pnpm-lock.yaml | 3 +++ 4 files changed, 15 insertions(+), 9 deletions(-) rename packages/nuxt-cli/test/fixtures/{dev/modules => }/log-dev-server-options.ts (65%) diff --git a/packages/nuxt-cli/package.json b/packages/nuxt-cli/package.json index 364a8ec9f..40c3deeec 100644 --- a/packages/nuxt-cli/package.json +++ b/packages/nuxt-cli/package.json @@ -60,6 +60,7 @@ "youch": "^4.1.0-beta.10" }, "devDependencies": { + "@nuxt/kit": "^4.0.0", "@nuxt/schema": "^4.0.0", "@types/node": "^22.16.3", "get-port-please": "^3.2.0", diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index 82575e73a..cb8d0b099 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -2,8 +2,8 @@ import { readFile } from 'node:fs/promises' import { join } from 'node:path' import { fileURLToPath } from 'node:url' import { getPort } from 'get-port-please' -import { x } from 'tinyexec' import { describe, expect, it } from 'vitest' +import { runCommand } from '../../src' const fixtureDir = fileURLToPath(new URL('../fixtures/dev', import.meta.url)) @@ -11,10 +11,13 @@ describe('dev server', () => { it('should expose dev server address to nuxt options', { timeout: 50_000 }, async () => { const host = '127.0.0.1' const port = await getPort({ host, port: 3031 }) - await x('nuxt', ['dev', `--host=${host}`, `--port=${port}`], { - nodeOptions: { cwd: fixtureDir }, - throwOnError: true, - }) + await runCommand('dev', [`--host=${host}`, `--port=${port}`, `--cwd=${fixtureDir}`], { + overrides: { + modules: [ + fileURLToPath(new URL('../fixtures/log-dev-server-options.ts', import.meta.url)), + ], + }, + }).catch(() => null) const options = await readFile(join(fixtureDir, '.nuxt', 'dev-server.json'), 'utf-8').then(JSON.parse) expect(options).toMatchObject({ https: false, diff --git a/packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts b/packages/nuxt-cli/test/fixtures/log-dev-server-options.ts similarity index 65% rename from packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts rename to packages/nuxt-cli/test/fixtures/log-dev-server-options.ts index 929a30866..f0ebb0795 100644 --- a/packages/nuxt-cli/test/fixtures/dev/modules/log-dev-server-options.ts +++ b/packages/nuxt-cli/test/fixtures/log-dev-server-options.ts @@ -1,6 +1,5 @@ -import { writeFile } from 'node:fs/promises' -import process from 'node:process' -import { defineNuxtModule, useNuxt } from 'nuxt/kit' +import { mkdir, writeFile } from 'node:fs/promises' +import { defineNuxtModule, useNuxt } from '@nuxt/kit' export default defineNuxtModule({ meta: { @@ -10,9 +9,9 @@ export default defineNuxtModule({ const nuxt = useNuxt() nuxt.hook('build:before', async () => { + await mkdir('.nuxt', { recursive: true }) await writeFile('.nuxt/dev-server.json', JSON.stringify(nuxt.options.devServer)) await nuxt.close() - process.exit(0) }) }, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 910cc4e29..b91257bea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -294,6 +294,9 @@ importers: specifier: ^4.1.0-beta.10 version: 4.1.0-beta.10 devDependencies: + '@nuxt/kit': + specifier: ^4.0.0 + version: 4.0.0(magicast@0.3.5) '@nuxt/schema': specifier: 4.0.0 version: 4.0.0 From cf558f413ca3f506a3660633ec234897bd6fc756 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 11:56:34 +0200 Subject: [PATCH 03/11] chore: fix knip --- knip.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/knip.json b/knip.json index 74faba98b..a3fc7daec 100644 --- a/knip.json +++ b/knip.json @@ -15,13 +15,13 @@ "pages/**", "server/**", "some-layer/**" - ], - "ignoreDependencies": [ - "@nuxt/test-utils", - "nuxt" ] }, "packages/nuxt-cli": { + "entry": [ + "src/index.ts", + "test/fixtures/*" + ], "ignoreDependencies": [ "c12", "clipboardy", @@ -34,7 +34,6 @@ "h3", "httpxy", "jiti", - "listhen", "nypm", "ofetch", "ohash", From 4df03f9448f2822da58604eb1321c508720e5887 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 12:05:21 +0200 Subject: [PATCH 04/11] test: relative to root --- packages/nuxt-cli/test/e2e/dev.spec.ts | 2 +- packages/nuxt-cli/test/fixtures/log-dev-server-options.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index cb8d0b099..8dac3f962 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -18,7 +18,7 @@ describe('dev server', () => { ], }, }).catch(() => null) - const options = await readFile(join(fixtureDir, '.nuxt', 'dev-server.json'), 'utf-8').then(JSON.parse) + const options = await readFile(join(fixtureDir, '.nuxt/dev-server.json'), 'utf-8').then(JSON.parse) expect(options).toMatchObject({ https: false, host, diff --git a/packages/nuxt-cli/test/fixtures/log-dev-server-options.ts b/packages/nuxt-cli/test/fixtures/log-dev-server-options.ts index f0ebb0795..7122f38d1 100644 --- a/packages/nuxt-cli/test/fixtures/log-dev-server-options.ts +++ b/packages/nuxt-cli/test/fixtures/log-dev-server-options.ts @@ -1,4 +1,5 @@ import { mkdir, writeFile } from 'node:fs/promises' +import { join } from 'node:path' import { defineNuxtModule, useNuxt } from '@nuxt/kit' export default defineNuxtModule({ @@ -10,7 +11,7 @@ export default defineNuxtModule({ nuxt.hook('build:before', async () => { await mkdir('.nuxt', { recursive: true }) - await writeFile('.nuxt/dev-server.json', JSON.stringify(nuxt.options.devServer)) + await writeFile(join(nuxt.options.rootDir, '.nuxt/dev-server.json'), JSON.stringify(nuxt.options.devServer)) await nuxt.close() }) }, From da328eae988210fa3d7eaa4cba48eb680dbdc6ec Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 12:21:41 +0200 Subject: [PATCH 05/11] test: add test for respecting devServer options --- packages/nuxt-cli/test/e2e/dev.spec.ts | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index 8dac3f962..f42c30670 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -1,4 +1,4 @@ -import { readFile } from 'node:fs/promises' +import { readFile, rm } from 'node:fs/promises' import { join } from 'node:path' import { fileURLToPath } from 'node:url' import { getPort } from 'get-port-please' @@ -9,6 +9,7 @@ const fixtureDir = fileURLToPath(new URL('../fixtures/dev', import.meta.url)) describe('dev server', () => { it('should expose dev server address to nuxt options', { timeout: 50_000 }, async () => { + await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) const host = '127.0.0.1' const port = await getPort({ host, port: 3031 }) await runCommand('dev', [`--host=${host}`, `--port=${port}`, `--cwd=${fixtureDir}`], { @@ -26,4 +27,28 @@ describe('dev server', () => { url: `http://${host}:${port}/`, }) }) + + it('should respect configured devServer options', { timeout: 50_000 }, async () => { + await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) + const host = '127.0.0.1' + const port = await getPort({ host, port: 3050 }) + await runCommand('dev', [`--cwd=${fixtureDir}`], { + overrides: { + devServer: { + host, + port, + }, + modules: [ + fileURLToPath(new URL('../fixtures/log-dev-server-options.ts', import.meta.url)), + ], + }, + }).catch(() => null) + const options = await readFile(join(fixtureDir, '.nuxt', 'dev-server.json'), 'utf-8').then(JSON.parse) + expect(options).toMatchObject({ + https: false, + host, + port, + url: `http://${host}:${port}/`, + }) + }) }) From 6dcf0428ab4b7b1dc3e39ccd16845b20e8502448 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 12:29:59 +0200 Subject: [PATCH 06/11] refactor: drop separate `createNuxtDevServer` wrapper --- packages/nuxi/src/dev/index.ts | 52 +++++++++++++++++++++++++-------- packages/nuxi/src/dev/socket.ts | 7 +++-- packages/nuxi/src/dev/utils.ts | 45 +++------------------------- 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/packages/nuxi/src/dev/index.ts b/packages/nuxi/src/dev/index.ts index 1152b1b38..6cba4ef79 100644 --- a/packages/nuxi/src/dev/index.ts +++ b/packages/nuxi/src/dev/index.ts @@ -1,10 +1,12 @@ import type { NuxtConfig } from '@nuxt/schema' import type { ListenOptions } from 'listhen' -import type { NuxtDevContext, NuxtDevIPCMessage, NuxtDevServer, NuxtParentIPCMessage } from './utils' +import type { NuxtDevContext, NuxtDevIPCMessage, NuxtParentIPCMessage } from './utils' import process from 'node:process' import defu from 'defu' -import { createNuxtDevServer, resolveDevServerDefaults, resolveDevServerOverrides } from './utils' +import { listen } from 'listhen' +import { createSocketListener } from './socket' +import { NuxtDevServer, resolveDevServerDefaults, resolveDevServerOverrides } from './utils' const start = Date.now() @@ -52,22 +54,48 @@ export async function initialize(devContext: NuxtDevContext, ctx: InitializeOpti https: devContext.proxy?.https, }, devContext.publicURLs) - // _PORT is used by `@nuxt/test-utils` to launch the dev server on a specific port - const listenOptions = _listenOptions === true || process.env._PORT - ? { port: process.env._PORT ?? 0, hostname: '127.0.0.1', showURL: false } - : _listenOptions - - // Init Nuxt dev - const devServer = await createNuxtDevServer({ + // Initialize dev server + const devServer = new NuxtDevServer({ cwd: devContext.cwd, - overrides: defu(ctx.data?.overrides, devServerOverrides), + overrides: defu( + ctx.data?.overrides, + ({ extends: devContext.args.extends } satisfies NuxtConfig) as NuxtConfig, + devServerOverrides, + ), defaults: devServerDefaults, logLevel: devContext.args.logLevel as 'silent' | 'info' | 'verbose', clear: !!devContext.args.clear, dotenv: { cwd: devContext.cwd, fileName: devContext.args.dotenv }, envName: devContext.args.envName, - devContext, - }, listenOptions) + devContext: { + proxy: devContext.proxy, + }, + }) + + // _PORT is used by `@nuxt/test-utils` to launch the dev server on a specific port + const listenOptions = _listenOptions === true || process.env._PORT + ? { port: process.env._PORT ?? 0, hostname: '127.0.0.1', showURL: false } + : _listenOptions + + // Attach internal listener + devServer.listener = listenOptions + ? await listen(devServer.handler, listenOptions) + : await createSocketListener(devServer.handler, devContext.proxy?.addr) + + if (process.env.DEBUG) { + // eslint-disable-next-line no-console + console.debug(`Using ${listenOptions ? 'network' : 'socket'} listener for Nuxt dev server.`) + } + + // Merge interface with public context + devServer.listener._url = devServer.listener.url + if (devContext.proxy?.url) { + devServer.listener.url = devContext.proxy.url + } + if (devContext.proxy?.urls) { + const _getURLs = devServer.listener.getURLs.bind(devServer.listener) + devServer.listener.getURLs = async () => Array.from(new Set([...devContext.proxy?.urls || [], ...(await _getURLs())])) + } let address: string diff --git a/packages/nuxi/src/dev/socket.ts b/packages/nuxi/src/dev/socket.ts index d87565346..f1ee0bea8 100644 --- a/packages/nuxi/src/dev/socket.ts +++ b/packages/nuxi/src/dev/socket.ts @@ -1,4 +1,5 @@ import type { RequestListener } from 'node:http' +import type { AddressInfo } from 'node:net' import { existsSync, unlinkSync } from 'node:fs' import { Server } from 'node:http' import os from 'node:os' @@ -43,7 +44,7 @@ export function parseSocketURL(url: string): { socketPath: string, protocol: 'ht return { socketPath, protocol: ssl ? 'https' : 'http' } } -export async function createSocketListener(handler: RequestListener, ssl = false) { +export async function createSocketListener(handler: RequestListener, proxyAddress?: AddressInfo) { const socketPath = generateSocketPath('nuxt-dev') const server = new Server(handler) @@ -56,10 +57,10 @@ export async function createSocketListener(handler: RequestListener, ssl = false } } await new Promise(resolve => server.listen({ path: socketPath }, resolve)) - const url = formatSocketURL(socketPath, ssl) + const url = formatSocketURL(socketPath) return { url, - address: { socketPath }, + address: { address: 'localhost', port: 3000, ...proxyAddress, socketPath }, async close() { try { server.removeAllListeners() diff --git a/packages/nuxi/src/dev/utils.ts b/packages/nuxi/src/dev/utils.ts index 49db232c3..9a21d8730 100644 --- a/packages/nuxi/src/dev/utils.ts +++ b/packages/nuxi/src/dev/utils.ts @@ -15,7 +15,6 @@ import { pathToFileURL } from 'node:url' import defu from 'defu' import { resolveModulePath } from 'exsolve' import { toNodeListener } from 'h3' -import { listen } from 'listhen' import { resolve } from 'pathe' import { debounce } from 'perfect-debounce' import { provider } from 'std-env' @@ -26,7 +25,7 @@ import { loadKit } from '../utils/kit' import { loadNuxtManifest, resolveNuxtManifest, writeNuxtManifest } from '../utils/nuxt' import { renderError } from './error' -import { createSocketListener, formatSocketURL } from './socket' +import { formatSocketURL } from './socket' export type NuxtParentIPCMessage = | { type: 'nuxt:internal:dev:context', context: NuxtDevContext, socket?: boolean } @@ -67,38 +66,8 @@ interface NuxtDevServerOptions { clear?: boolean defaults: NuxtConfig overrides: NuxtConfig - port?: string | number loadingTemplate?: ({ loading }: { loading: string }) => string - devContext: NuxtDevContext -} - -export async function createNuxtDevServer(options: NuxtDevServerOptions, listenOptions?: true | Partial) { - // Initialize dev server - const devServer = new NuxtDevServer(options) - - // Attach internal listener - devServer.listener = listenOptions - ? await listen(devServer.handler, typeof listenOptions === 'object' - ? listenOptions - : { port: options.port ?? 0, hostname: '127.0.0.1', showURL: false }) - : await createSocketListener(devServer.handler) - - if (process.env.DEBUG) { - // eslint-disable-next-line no-console - console.debug(`Using ${listenOptions ? 'network' : 'socket'} listener for Nuxt dev server.`) - } - - // Merge interface with public context - devServer.listener._url = devServer.listener.url - if (options.devContext.proxy?.url) { - devServer.listener.url = options.devContext.proxy.url - } - if (options.devContext.proxy?.urls) { - const _getURLs = devServer.listener.getURLs.bind(devServer.listener) - devServer.listener.getURLs = async () => Array.from(new Set([...options.devContext.proxy?.urls || [], ...(await _getURLs())])) - } - - return devServer + devContext: Pick } // https://regex101.com/r/7HkR5c/1 @@ -126,7 +95,7 @@ export class NuxtDevServer extends EventEmitter { handler: RequestListener listener: Pick & { _url?: string - address: { socketPath: string } | AddressInfo + address: Omit & { socketPath: string } | AddressInfo } constructor(private options: NuxtDevServerOptions) { @@ -234,7 +203,6 @@ export class NuxtDevServer extends EventEmitter { defaults: defu(this.options.defaults, devServerDefaults), overrides: { logLevel: this.options.logLevel as 'silent' | 'info' | 'verbose', - ...(this.options.devContext.args.extends && { extends: this.options.devContext.args.extends }), ...this.options.overrides, vite: { clearScreen: this.options.clear, @@ -314,12 +282,7 @@ export class NuxtDevServer extends EventEmitter { // Sync internal server info to the internals // It is important for vite-node to use the internal URL but public proto - const addr = { - port: 3000, - address: 'localhost', - ...this.options.devContext.proxy?.addr, - ...this.listener.address, - } + const addr = this.listener.address this._currentNuxt.options.devServer.host = addr.address this._currentNuxt.options.devServer.port = addr.port this._currentNuxt.options.devServer.url = 'socketPath' in addr From 70944793d12ac75bc58bc6de2ada947bcdd4912f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 12:32:39 +0200 Subject: [PATCH 07/11] fix: simplify url creation --- packages/nuxi/src/dev/utils.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/nuxi/src/dev/utils.ts b/packages/nuxi/src/dev/utils.ts index 9a21d8730..cf270452d 100644 --- a/packages/nuxi/src/dev/utils.ts +++ b/packages/nuxi/src/dev/utils.ts @@ -285,9 +285,7 @@ export class NuxtDevServer extends EventEmitter { const addr = this.listener.address this._currentNuxt.options.devServer.host = addr.address this._currentNuxt.options.devServer.port = addr.port - this._currentNuxt.options.devServer.url = 'socketPath' in addr - ? this.options.devContext.proxy?.url || getAddressURL(addr, !!this.listener.https) - : getAddressURL(addr, !!this.listener.https) + this._currentNuxt.options.devServer.url = getAddressURL(addr, !!this.listener.https) this._currentNuxt.options.devServer.https = this.options.devContext.proxy?.https as boolean | { key: string, cert: string } if (this.listener.https && !process.env.NODE_TLS_REJECT_UNAUTHORIZED) { From 194597f87c736097bbc340f3181834492e33068d Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 12:33:53 +0200 Subject: [PATCH 08/11] test: expect failure for now --- packages/nuxt-cli/test/e2e/dev.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index f42c30670..abeeb4936 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -28,7 +28,7 @@ describe('dev server', () => { }) }) - it('should respect configured devServer options', { timeout: 50_000 }, async () => { + it.fails('should respect configured devServer options', { timeout: 50_000 }, async () => { await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) const host = '127.0.0.1' const port = await getPort({ host, port: 3050 }) From 77b5799b27678e2a8c4c893d8b965ba0bc7109d0 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 12:47:03 +0200 Subject: [PATCH 09/11] chore: comment --- packages/nuxt-cli/test/e2e/dev.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index abeeb4936..1b6a4d606 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -28,6 +28,7 @@ describe('dev server', () => { }) }) + // TODO: fix this test it.fails('should respect configured devServer options', { timeout: 50_000 }, async () => { await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) const host = '127.0.0.1' @@ -43,7 +44,7 @@ describe('dev server', () => { ], }, }).catch(() => null) - const options = await readFile(join(fixtureDir, '.nuxt', 'dev-server.json'), 'utf-8').then(JSON.parse) + const options = await readFile(join(fixtureDir, '.nuxt/dev-server.json'), 'utf-8').then(JSON.parse) expect(options).toMatchObject({ https: false, host, From d44c29b7c7d0b0005a73ae50f390292061b3fdc2 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 13:51:39 +0200 Subject: [PATCH 10/11] Update dev.spec.ts --- packages/nuxt-cli/test/e2e/dev.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index 1b6a4d606..4eb98ee9a 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -28,8 +28,7 @@ describe('dev server', () => { }) }) - // TODO: fix this test - it.fails('should respect configured devServer options', { timeout: 50_000 }, async () => { + it('should respect configured devServer options', { timeout: 50_000 }, async () => { await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) const host = '127.0.0.1' const port = await getPort({ host, port: 3050 }) From 8c005fb80a779607a0ec72f5590c152b23ca6388 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 20 Jul 2025 18:09:52 +0200 Subject: [PATCH 11/11] test: close after running --- packages/nuxt-cli/test/e2e/dev.spec.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/nuxt-cli/test/e2e/dev.spec.ts b/packages/nuxt-cli/test/e2e/dev.spec.ts index 4eb98ee9a..c7beda739 100644 --- a/packages/nuxt-cli/test/e2e/dev.spec.ts +++ b/packages/nuxt-cli/test/e2e/dev.spec.ts @@ -12,13 +12,14 @@ describe('dev server', () => { await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) const host = '127.0.0.1' const port = await getPort({ host, port: 3031 }) - await runCommand('dev', [`--host=${host}`, `--port=${port}`, `--cwd=${fixtureDir}`], { + const { result: { close } } = await runCommand('dev', [`--host=${host}`, `--port=${port}`, `--cwd=${fixtureDir}`], { overrides: { modules: [ fileURLToPath(new URL('../fixtures/log-dev-server-options.ts', import.meta.url)), ], }, - }).catch(() => null) + }) as any + await close() const options = await readFile(join(fixtureDir, '.nuxt/dev-server.json'), 'utf-8').then(JSON.parse) expect(options).toMatchObject({ https: false, @@ -32,7 +33,7 @@ describe('dev server', () => { await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) const host = '127.0.0.1' const port = await getPort({ host, port: 3050 }) - await runCommand('dev', [`--cwd=${fixtureDir}`], { + const { result: { close } } = await runCommand('dev', [`--cwd=${fixtureDir}`], { overrides: { devServer: { host, @@ -42,7 +43,8 @@ describe('dev server', () => { fileURLToPath(new URL('../fixtures/log-dev-server-options.ts', import.meta.url)), ], }, - }).catch(() => null) + }) as any + await close() const options = await readFile(join(fixtureDir, '.nuxt/dev-server.json'), 'utf-8').then(JSON.parse) expect(options).toMatchObject({ https: false,