feat(core): implement non-recursive watcher to avoid unnecessary watchers being registered#34345
Closed
MaxKless wants to merge 1 commit into
Closed
feat(core): implement non-recursive watcher to avoid unnecessary watchers being registered#34345MaxKless wants to merge 1 commit into
MaxKless wants to merge 1 commit into
Conversation
…hers being registered
Contributor
|
View your CI Pipeline Execution ↗ for commit 588c365
☁️ Nx Cloud last updated this comment at |
✅ Deploy Preview for nx-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Contributor
|
I'll handle this in #34329 |
Contributor
|
This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Current Behavior
The Nx native file watcher uses watchexec (v3.0.1) which internally calls notify::INotifyWatcher with RecursiveMode::Recursive. This walks every subdirectory in the
workspace and registers an OS-level watch on each one. The ignore patterns (node_modules/, .git/, .nx/, etc.) are only applied as event filters via the watchexec Filterer
trait — they don't prevent the watch registration itself.
In practice, a typical node_modules contains 30-50k+ subdirectories. All of these get watches registered, even though every event from them is immediately filtered out and
discarded. This causes two problems:
reached.
On the Nx repo itself: 59,568 directories get watches, of which 46,086 are ignored (node_modules, .git, .nx).
Expected Behavior
The watcher only registers watches for directories that aren't ignored. Using the Nx repo as a benchmark:
For typical user projects with larger node_modules trees, the reduction will be even greater.
The NAPI API surface is unchanged — TypeScript consumers see no difference.
Approach
Upgrade watchexec from 3.0.1 to 4.1.0, which introduces WatchedPath::non_recursive(). Instead of passing a single recursive root path to watchexec, we walk the directory
tree ourselves using ignore::WalkBuilder (the same crate and pattern already used in walker.rs) and pass each non-ignored directory as a WatchedPath::non_recursive().
Key design decisions
everywhere. Same code path on all platforms keeps things simple.
parent_gitignore_files() for git boundary detection, .nxignore support, and filter_entry for the watcher's static ignore globs.
CreateKind::Folder events and re-walks the workspace to update the watch set. This required removing the #[cfg(target_os = "linux")] guard on directory events in the
filterer — previously directory events were only allowed through on Linux (for inotify race condition handling), but now all platforms need them to detect new directories.
circular Arc reference (Watchexec → Config → on_action closure → Arc) that would prevent cleanup.
tracking structure, we re-walk the workspace on directory creation. This is simple, correct, and fast since WalkBuilder skips ignored directories.