Reduce Linux file-watcher load on large codebases by excluding nested build/dependency dirs (#7453)

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Brennan Benson 2026-07-05 15:33:38 -07:00 committed by GitHub
parent 7953240135
commit 3bcfae1767
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 5 deletions

View File

@ -32,8 +32,18 @@ describe('buildParcelWatcherIgnoreOption', () => {
}
})
it('passes the plain list through on other platforms', () => {
setPlatform('linux')
expect(buildParcelWatcherIgnoreOption(WATCHER_IGNORE_DIRS)).toEqual(WATCHER_IGNORE_DIRS)
it('expands to nested globs on Linux/Windows so nested node_modules/.git are excluded', () => {
for (const platform of ['linux', 'win32'] as const) {
setPlatform(platform)
const option = buildParcelWatcherIgnoreOption(WATCHER_IGNORE_DIRS)
// @parcel/watcher resolves plain names to top-level-only absolute paths on
// these platforms, so nested dirs must be matched via depth-agnostic globs.
for (const dir of WATCHER_IGNORE_DIRS) {
expect(option).toContain(`**/${dir}`)
expect(option).toContain(`**/${dir}/**`)
}
// No plain (glob-free) entries — those would only exclude the top level.
expect(option.every((entry) => entry.includes('*'))).toBe(true)
}
})
})

View File

@ -25,7 +25,12 @@ export const MACOS_FSEVENTS_EXCLUSION_PATH_LIMIT = 8
export function buildParcelWatcherIgnoreOption(ignoreDirs: readonly string[]): string[] {
if (process.platform !== 'darwin') {
return [...ignoreDirs]
// Linux/Windows: @parcel/watcher resolves plain names to top-level-only
// absolute paths, so nested node_modules/.git/build/etc. (monorepos) get
// fully watched — on Linux that means one inotify watch per nested dir,
// exhausting fs.inotify.max_user_watches. Nested globs match at any depth
// (and **/dir still matches the top-level dir), pruning those subtrees.
return ignoreDirs.flatMap((dir) => [`**/${dir}`, `**/${dir}/**`])
}
return [
...ignoreDirs.slice(0, MACOS_FSEVENTS_EXCLUSION_PATH_LIMIT),

View File

@ -29,6 +29,10 @@ import { RelayStreamRegistry } from './fs-stream-registry'
import { scanWorkspaceSpaceDirectory } from './workspace-space-scan'
import { buildRelayCommandEnv } from './relay-command-env'
import { assertNoClobberRenameDestinationAvailable } from '../shared/filesystem-rename-collision'
import {
WATCHER_IGNORE_DIRS,
buildParcelWatcherIgnoreOption
} from '../main/ipc/filesystem-watcher-ignore'
type WatchState = {
rootPath: string
@ -408,7 +412,9 @@ export class FsHandler {
}))
this.dispatcher.notify('fs.changed', { events: mapped })
},
{ ignore: ['.git', 'node_modules', 'dist', 'build', '.next', '.cache', '__pycache__'] }
// Why: align remote-Linux watchers with the shared nested-glob exclusion
// so nested node_modules/.git don't exhaust inotify on large codebases.
{ ignore: buildParcelWatcherIgnoreOption(WATCHER_IGNORE_DIRS) }
)
watchState.unwatchFn = () => {
void subscription.unsubscribe()