Skip to content

Commit 2fc475b

Browse files
committed
fix(dev): avoid recursive fs watching
1 parent 99b4136 commit 2fc475b

File tree

1 file changed

+48
-16
lines changed

1 file changed

+48
-16
lines changed

packages/nuxi/src/dev/utils.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { IncomingMessage, RequestListener, ServerResponse } from 'node:http
77
import type { AddressInfo } from 'node:net'
88

99
import EventEmitter from 'node:events'
10-
import { watch } from 'node:fs'
10+
import { existsSync, watch } from 'node:fs'
1111
import { mkdir } from 'node:fs/promises'
1212

1313
import process from 'node:process'
@@ -112,7 +112,7 @@ interface DevServerEventMap {
112112
export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
113113
private _handler?: RequestListener
114114
private _distWatcher?: FSWatcher
115-
private _configWatcher?: FSWatcher
115+
private _configWatcher?: () => void
116116
private _currentNuxt?: NuxtWithServer
117117
private _loadingMessage?: string
118118
private _loadingError?: Error
@@ -185,7 +185,7 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
185185

186186
async init() {
187187
await this.load()
188-
await this._watchConfig()
188+
this._watchConfig()
189189
}
190190

191191
async load(reload?: boolean, reason?: string) {
@@ -204,7 +204,7 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
204204

205205
async close() {
206206
this._distWatcher?.close()
207-
this._configWatcher?.close()
207+
this._configWatcher?.()
208208
if (this._currentNuxt) {
209209
await this._currentNuxt.close()
210210
}
@@ -350,18 +350,13 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
350350
this.emit('ready', 'socketPath' in addr ? formatSocketURL(addr.socketPath, !!this.listener.https) : `http://127.0.0.1:${addr.port}`)
351351
}
352352

353-
async _watchConfig() {
354-
this._configWatcher = watch(this.options.cwd, { recursive: true })
355-
356-
this._configWatcher.on('change', (_event, file: string) => {
357-
if (file === (this.options.dotenv.fileName || '.env')) {
358-
this.emit('restart')
359-
}
360-
361-
if (RESTART_RE.test(file)) {
362-
this.loadDebounced(true, `${file} updated`)
363-
}
364-
})
353+
_watchConfig() {
354+
this._configWatcher = createConfigWatcher(
355+
this.cwd,
356+
this.options.dotenv.fileName,
357+
() => this.emit('restart'),
358+
file => this.loadDebounced(true, `${file} updated`),
359+
)
365360
}
366361
}
367362

@@ -402,3 +397,40 @@ export function resolveDevServerDefaults(listenOptions: Partial<Pick<ListenOptio
402397

403398
return defaultConfig
404399
}
400+
401+
function createConfigWatcher(cwd: string, dotenvFileName = '.env', onRestart: () => void, onReload: (file: string) => void) {
402+
const configWatcher = watch(cwd)
403+
let configDirWatcher = existsSync(resolve(cwd, '.config')) ? createConfigDirWatcher(cwd, onReload) : undefined
404+
405+
configWatcher.on('change', (_event, file: string) => {
406+
if (file === dotenvFileName) {
407+
onRestart()
408+
}
409+
410+
if (RESTART_RE.test(file)) {
411+
onReload(file)
412+
}
413+
414+
if (file === '.config') {
415+
configDirWatcher ||= createConfigDirWatcher(cwd, onReload)
416+
}
417+
})
418+
419+
return () => {
420+
configWatcher.close()
421+
configDirWatcher?.()
422+
}
423+
}
424+
425+
function createConfigDirWatcher(cwd: string, onReload: (file: string) => void) {
426+
const configDir = resolve(cwd, '.config')
427+
428+
const configDirWatcher = watch(configDir)
429+
configDirWatcher.on('change', (_event, file: string) => {
430+
if (RESTART_RE.test(file)) {
431+
onReload(file)
432+
}
433+
})
434+
435+
return () => configDirWatcher.close()
436+
}

0 commit comments

Comments
 (0)