Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 7 additions & 17 deletions packages/nuxt-cli/src/dev/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,30 +217,14 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
return this.load(true, reason)
})

let _initResolve: () => void
const _initPromise = new Promise<void>((resolve) => {
_initResolve = resolve
})
this.once('ready', () => {
_initResolve()
})

this.#cwd = options.cwd

this.handler = async (req, res) => {
if (this.#loadingError) {
void renderError(req, res, this.#loadingError)
return
}
await _initPromise
if (this.#handler) {
this.#inflightResponses.add(res)
res.once('close', () => {
this.#inflightResponses.delete(res)
})
this.#handler(req, res)
}
else {
if (!this.#handler) {
await this.#renderLoadingScreen(req, res).catch((error) => {
debug('Could not render the loading screen:', error)
if (res.headersSent) {
Expand All @@ -250,7 +234,13 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
res.statusCode = 503
res.end('Dev server is loading...')
})
return
}
this.#inflightResponses.add(res)
res.once('close', () => {
this.#inflightResponses.delete(res)
})
this.#handler(req, res)
}
}

Expand Down
59 changes: 59 additions & 0 deletions packages/nuxt-cli/test/e2e/dev.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { readFile, rm } from 'node:fs/promises'
import { join } from 'node:path'
import { setTimeout as sleep } from 'node:timers/promises'
import { fileURLToPath } from 'node:url'
import { getPort } from 'get-port-please'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { runCommand } from '../../src'
import { NuxtDevServer } from '../../src/dev/utils'
import { createDevFixture } from '../utils'

const NEWLINE_RE = /\r?\n/
Expand All @@ -20,6 +22,63 @@ describe('dev server', () => {
vi.unstubAllEnvs()
})

it('should serve the loading screen during initial startup', { timeout: 50_000 }, async () => {
const host = '127.0.0.1'
const port = await getPort({ host, port: 3030 })
const buildDir = join(fixtureDir, `.nuxt-loading-screen-${port}`)
const devServer = new NuxtDevServer({
cwd: fixtureDir,
dotenv: {},
overrides: {
buildDir,
hooks: {
ready: () => sleep(2000),
},
},
loadingTemplate: ({ loading }) => `<p>${loading}</p>`,
listenOverrides: { hostname: host, port },
})
const initPromise = devServer.init()
let initializationFailure: { error: unknown } | undefined
void initPromise.catch((error) => {
initializationFailure = { error }
})

try {
const deadline = Date.now() + 10_000
let response: Response | undefined
while (!response) {
if (initializationFailure) {
throw initializationFailure.error
}
if (Date.now() >= deadline) {
throw new Error('Timed out waiting for the dev server listener')
}
response = await fetch(`http://${host}:${port}`, {
headers: { accept: 'text/html' },
}).catch(() => undefined)
if (!response) {
await sleep(20)
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

expect(response.status).toBe(503)
expect(response.headers.get('refresh')).toBe('3')
await expect(response.text()).resolves.toContain('Starting Nuxt...')
await initPromise
}
finally {
await initPromise.catch(() => {})
devServer.closeWatchers()
await Promise.all([
devServer.listener?.close(),
devServer.close(),
])
devServer.releaseLock()
await rm(buildDir, { recursive: true, force: true })
}
})

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'
Expand Down
Loading