diff --git a/packages/angular/build/src/tools/esbuild/watcher.ts b/packages/angular/build/src/tools/esbuild/watcher.ts index b6e26f5c72af..1b9fd15d4561 100644 --- a/packages/angular/build/src/tools/esbuild/watcher.ts +++ b/packages/angular/build/src/tools/esbuild/watcher.ts @@ -141,6 +141,12 @@ class WatcherQueue { private currentChangedFiles: ChangedFiles | undefined; private isClosed = false; private timeoutId: NodeJS.Timeout | undefined; + private firstChangeTime: number | undefined; + + constructor( + private readonly debounceMs = 100, + private readonly maxWaitMs = 500, + ) {} addChange(type: 'added' | 'modified' | 'removed', file: string): void { if (this.isClosed) { @@ -167,16 +173,25 @@ class WatcherQueue { } private scheduleFlush(): void { + const now = Date.now(); + const firstChangeTime = (this.firstChangeTime ??= now); + if (this.timeoutId) { clearTimeout(this.timeoutId); } + + const elapsed = now - firstChangeTime; + const remainingMaxWait = Math.max(0, this.maxWaitMs - elapsed); + const delay = Math.min(this.debounceMs, remainingMaxWait); + this.timeoutId = setTimeout(() => { this.timeoutId = undefined; this.flush(); - }, 250); + }, delay); } private flush(): void { + this.firstChangeTime = undefined; if ( this.currentChangedFiles && this.currentChangedFiles.all.length > 0 && @@ -224,6 +239,7 @@ class WatcherQueue { clearTimeout(this.timeoutId); this.timeoutId = undefined; } + this.firstChangeTime = undefined; this.isClosed = true; this.currentChangedFiles = undefined; @@ -511,7 +527,16 @@ async function createChokidarWatcher( ): Promise { const chokidar = chokidarModule ?? (await import('chokidar')); const watchedFiles = new Set(); - const queue = new WatcherQueue(); + + let queue: WatcherQueue; + if (options?.polling) { + const pollingInterval = options.interval ?? 100; + const debounceMs = Math.min(250, Math.max(100, Math.ceil(pollingInterval * 1.5))); + const maxWaitMs = Math.max(500, debounceMs * 3); + queue = new WatcherQueue(debounceMs, maxWaitMs); + } else { + queue = new WatcherQueue(); + } const rootDir = options?.cwd ?? process.cwd(); const isCaseSensitive = isFileSystemCaseSensitive(rootDir);