Chokidar

repository·main·Indexed 11 days ago

https://github.com/paulmillr/chokidar

A minimal and efficient cross-platform file watching library for Node.js. It provides a consistent API for monitoring file system events, handling atomic writes, and recursive watching. Version 5.0.0 includes an FSWatcher instance for managing paths via .add(), .unwatch(), and .close(), and supports advanced configuration options like awaitWriteFinish for large file writes and custom path filtering via the ignored option.

Tokens
3K
Snippets
8
Records
12
Agent score
46%

What's inside Chokidar

  1. Upgrade to Chokidar v4: Handling Glob Removal

    main

    In version 4, Chokidar removed built-in glob support. If your code relies on glob patterns (e.g., **/*.js), you must migrate to one of the following two patterns:

    Option 1: Use the ignored option

    Watch a directory and use the ignored function to filter for specific file extensions or patterns.

    Option 2: Use node:fs/promises globs

    Use the native Node.js glob function to resolve paths first, then pass the resulting array of paths to chokidar.watch().

    Note on Unwatching: Because globs are no longer supported, you cannot call unwatch() with a glob string. You must resolve the glob to an array of paths first and pass that array to unwatch().

    // v3 (Old way - Glob support included)
    chok.watch('**/*.js');
    chok.unwatch('**/*.js');
    
    // v4 (New way - Option 1: Using ignored function)
    chok.watch('.', {
      ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'),
    });
    
    // v4 (New way - Option 2: Using native Node.js globs)
    import { glob } from 'node:fs/promises';
    const watcher = chok.watch(await Array.fromAsync(glob('**/*.js')));
    
    // v4 (New way - Unwatching with resolved paths)
    chok.unwatch(await Array.fromAsync(glob('**/*.js')));
  2. Configure Chokidar watcher options

    main

    The chokidar.watch method accepts an options object to fine-tune behavior.

    Persistence

    • persistent (default: true): Whether the process should continue running as long as files are being watched.

    Path Filtering

    • ignored: A function, regex, or path defining what to ignore. If a function is used, it receives (path, stats). The entire path is tested.
    • ignoreInitial (default: false): If true, add/addDir events are not emitted for existing files during the initial scan.
    • followSymlinks (default: true): Whether to follow symbolic links.
    • cwd (no default): The base directory for deriving watch paths. Emitted paths will be relative to this.

    Performance

    • usePolling (default: false): Uses fs.watchFile (polling) instead of fs.watch. Set to true for watching files over a network.
    • interval (default: 100): Polling interval in ms (used when usePolling is true).
    • binaryInterval (default: 300): Polling interval for binary files.
    • alwaysStat (default: false): If true, ensures fs.Stats is passed to add, addDir, and change events even if not provided by the OS.
    • depth (default: undefined): Limits how many levels of subdirectories are traversed.
    • awaitWriteFinish (default: false): If true, waits for a file size to remain constant for a stabilityThreshold (default 2000ms) before emitting add/change events. Useful for large/chunked writes.

    Errors & Atomic Writes

    • ignorePermissionErrors (default: false): If true, suppresses EPERM or EACCES errors.
    • atomic (default: true if not using useFsEvents or usePolling): Filters out artifacts from editors using atomic writes. If a file is re-added within 100ms of being deleted, it emits change instead of unlink + add. You can set this to a custom millisecond value.
  3. Define ignored paths using Matcher

    main

    The ignored option accepts a Matcher, which can be one of the following types:

    • string: Matches the exact path.
    • RegExp: Matches the path against the regular expression.
    • MatchFunction: A function (val: string, stats?: Stats) => boolean that returns true if the path should be ignored.
    • MatcherObject: An object specifying a path and whether to be recursive:
      { path: 'some/path', recursive: true }
  4. Troubleshoot EMFILE and ENOSPC errors

    main

    If Chokidar runs out of file handles, you may see EMFILE or ENOSPC errors.

    Exhausted file handles for generic fs operations

    • Solution 1: Use graceful-fs to monkey-patch the native fs module:
      let fs = require('fs');
      let grfs = require('graceful-fs');
      grfs.gracefulify(fs);
    • Solution 2: Increase the OS limit (Linux):
      echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
    
    ### Exhausted file handles for `fs.watch`
    - If `graceful-fs` and OS tuning do not work, switch to polling by setting `usePolling: true` in your Chokidar options.
    
  5. Quickstart: Watch a directory with Chokidar

    main

    You can start watching the current directory with a single line of code. The all event emits every file system event along with its path.

    import chokidar from 'chokidar';
    
    // One-liner for current directory
    chokidar.watch('.').on('all', (event, path) => {
      console.log(event, path);
    });
  6. Manage watched paths with FSWatcher methods

    main

    An FSWatcher instance provides methods to dynamically update what is being watched:

    • .add(path | paths): Add a single path or an array of paths to the watcher.
    • .unwatch(path | paths): Stop watching specific files or directories.
    • .getWatched(): Returns an object where keys are directory paths and values are arrays of filenames currently being watched.
    • .close(): Asynchronous. Removes all listeners and stops watching. Always await this method to prevent bugs.
    const watcher = chokidar.watch('some-dir');
    
    // Add new files to watch
    watcher.add('new-file.txt');
    watcher.add(['file2.txt', 'file3.txt']);
    
    // Get current watched paths
    let watchedPaths = watcher.getWatched();
    
    // Stop watching specific files
    await watcher.unwatch('new-file.txt');
    
    // Stop the watcher entirely
    await watcher.close();
  7. Use FSWatcher to monitor file events

    main

    The chokidar.watch(paths, [options]) method returns an FSWatcher instance. You can listen to specific events like add, change, and unlink to react to file system changes.

    Available Events

    • add: File added
    • addDir: Directory added
    • change: File changed
    • unlink: File removed
    • unlinkDir: Directory removed
    • ready: Initial scan complete
    • error: Watcher error
    • all: Emits all events (except ready, raw, and error) as (event, path)
    • raw: Internal raw event info (use with caution)
    import chokidar from 'chokidar';
    
    const watcher = chokidar.watch('path/to/watch', { persistent: true });
    
    watcher
      .on('add', (path) => console.log(`File ${path} added`))
      .on('change', (path, stats) => console.log(`File ${path} changed`))
      .on('unlink', (path) => console.log(`File ${path} removed`))
      .on('ready', () => console.log('Ready for changes'));
  8. Configure ChokidarOptions

    main

    When calling watch(paths, options), you can provide a ChokidarOptions object to customize watcher behavior.

    Core Options

    • persistent: (boolean) Whether to keep the watcher running. Defaults to true.
    • ignoreInitial: (boolean) Whether to ignore existing files when the watcher starts. Defaults to false.
    • followSymlinks: (boolean) Whether to follow symbolic links. Defaults to true.
    • cwd: (string) The current working directory for relative paths.
    • usePolling: (boolean) Whether to use polling instead of native OS events. Defaults to false (except on IBM i).
    • interval: (number) Polling interval in milliseconds. Defaults to 100.
    • binaryInterval: (number) Polling interval for binary files. Defaults to 300.
    • atomic: (boolean | number) Enables atomic write normalization. If a number, it specifies the delay in milliseconds. Defaults to true (or !usePolling).
    • ignorePermissionErrors: (boolean) Whether to ignore errors like EPERM or EACCES. Defaults to false.
    • depth: (number) Maximum depth to watch.
    • alwaysStat: (boolean) Whether to always provide Stats objects with events.

    Advanced Options

    • ignored: (Matcher | Matcher[]) A string, RegExp, function, or MatcherObject used to filter out paths.
    • awaitWriteFinish: (boolean | Partial<AWF>) If true, the watcher waits for a file to stop changing in size before emitting an event. If an object, you can configure:
      • stabilityThreshold: (number) Milliseconds the file size must remain constant. Defaults to 2000.
      • pollInterval: (number) How often to check the file size. Defaults to 100.
  9. Use awaitWriteFinish to handle large file writes

    main

    To prevent emitting events before a file has finished being written (e.g., during a large copy operation), use the awaitWriteFinish option. The watcher will poll the file and only emit the add or change event once the file size remains stable for the specified stabilityThreshold.

    const watcher = watch('.', {
      awaitWriteFinish: {
        stabilityThreshold: 3000,
        pollInterval: 200
      }
    });
    import { watch } from 'chokidar';
    
    const watcher = watch('.', {
      awaitWriteFinish: {
        stabilityThreshold: 3000,
        pollInterval: 200
      }
    });
  10. Manage watcher lifecycle with add(), unwatch(), and close()

    main

    The FSWatcher instance provides methods to manage what is being watched during its lifecycle:

    • add(paths: Path | Path[]): Adds new paths to the existing watcher. Returns the FSWatcher instance for chaining.
    • unwatch(paths: Path | Path[]): Stops watching specified paths and ignores future events from them. Returns the FSWatcher instance for chaining.
    • close(): Returns a Promise that resolves when all watchers are closed and all listeners are removed.
    const watcher = watch('src');
    
    // Later, add more paths
    watcher.add(['test', 'docs']);
    
    // Stop watching a specific directory
    watcher.unwatch('src/temp');
    
    // Shut down the watcher
    await watcher.close();
  11. Watch files and directories with watch()

    main

    Use the watch function to create an FSWatcher instance that monitors file system changes. You can pass a single string or an array of strings representing the paths to watch. The function returns an FSWatcher instance, which supports method chaining.

    Common events to listen for include add, addDir, change, unlink, unlinkDir, all, and error.

    import { watch } from 'chokidar';
    
    // Basic usage
    const watcher = watch('.').on('all', (event, path) => { 
      console.log(event, path);
    });
    
    // Usage with options
    const watcherWithOpts = watch('.', {
      atomic: true,
      awaitWriteFinish: true,
      ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js')
    });