1
|
# Chokidar [![Weekly downloads](https://img.shields.io/npm/dw/chokidar.svg)](https://github.com/paulmillr/chokidar) [![Yearly downloads](https://img.shields.io/npm/dy/chokidar.svg)](https://github.com/paulmillr/chokidar) [![Mac/Linux Build Status](https://img.shields.io/travis/paulmillr/chokidar/master.svg?label=Mac%20OSX%20%26%20Linux)](https://travis-ci.org/paulmillr/chokidar) [![Windows Build status](https://img.shields.io/appveyor/ci/paulmillr/chokidar/master.svg?label=Windows)](https://ci.appveyor.com/project/paulmillr/chokidar/branch/master) [![Coverage Status](https://coveralls.io/repos/paulmillr/chokidar/badge.svg)](https://coveralls.io/r/paulmillr/chokidar)
|
2
|
|
3
|
> A neat wrapper around node.js fs.watch / fs.watchFile / FSEvents.
|
4
|
|
5
|
[![NPM](https://nodei.co/npm/chokidar.png)](https://www.npmjs.com/package/chokidar)
|
6
|
|
7
|
## Why?
|
8
|
Node.js `fs.watch`:
|
9
|
|
10
|
* Doesn't report filenames on MacOS.
|
11
|
* Doesn't report events at all when using editors like Sublime on MacOS.
|
12
|
* Often reports events twice.
|
13
|
* Emits most changes as `rename`.
|
14
|
* Has [a lot of other issues](https://github.com/nodejs/node/search?q=fs.watch&type=Issues)
|
15
|
* Does not provide an easy way to recursively watch file trees.
|
16
|
|
17
|
Node.js `fs.watchFile`:
|
18
|
|
19
|
* Almost as bad at event handling.
|
20
|
* Also does not provide any recursive watching.
|
21
|
* Results in high CPU utilization.
|
22
|
|
23
|
Chokidar resolves these problems.
|
24
|
|
25
|
Initially made for **[Brunch](http://brunch.io)** (an ultra-swift web app build tool), it is now used in
|
26
|
[gulp](https://github.com/gulpjs/gulp/),
|
27
|
[karma](http://karma-runner.github.io),
|
28
|
[PM2](https://github.com/Unitech/PM2),
|
29
|
[browserify](http://browserify.org/),
|
30
|
[webpack](http://webpack.github.io/),
|
31
|
[BrowserSync](http://www.browsersync.io/),
|
32
|
[Microsoft's Visual Studio Code](https://github.com/microsoft/vscode),
|
33
|
and [many others](https://www.npmjs.org/browse/depended/chokidar/).
|
34
|
It has proven itself in production environments.
|
35
|
|
36
|
## How?
|
37
|
Chokidar does still rely on the Node.js core `fs` module, but when using
|
38
|
`fs.watch` and `fs.watchFile` for watching, it normalizes the events it
|
39
|
receives, often checking for truth by getting file stats and/or dir contents.
|
40
|
|
41
|
On MacOS, chokidar by default uses a native extension exposing the Darwin
|
42
|
`FSEvents` API. This provides very efficient recursive watching compared with
|
43
|
implementations like `kqueue` available on most \*nix platforms. Chokidar still
|
44
|
does have to do some work to normalize the events received that way as well.
|
45
|
|
46
|
On other platforms, the `fs.watch`-based implementation is the default, which
|
47
|
avoids polling and keeps CPU usage down. Be advised that chokidar will initiate
|
48
|
watchers recursively for everything within scope of the paths that have been
|
49
|
specified, so be judicious about not wasting system resources by watching much
|
50
|
more than needed.
|
51
|
|
52
|
## Getting started
|
53
|
Install with npm:
|
54
|
|
55
|
```sh
|
56
|
npm install chokidar
|
57
|
```
|
58
|
|
59
|
Then `require` and use it in your code:
|
60
|
|
61
|
```javascript
|
62
|
var chokidar = require('chokidar');
|
63
|
|
64
|
// One-liner for current directory, ignores .dotfiles
|
65
|
chokidar.watch('.', {ignored: /(^|[\/\\])\../}).on('all', (event, path) => {
|
66
|
console.log(event, path);
|
67
|
});
|
68
|
```
|
69
|
|
70
|
```javascript
|
71
|
// Example of a more typical implementation structure:
|
72
|
|
73
|
// Initialize watcher.
|
74
|
var watcher = chokidar.watch('file, dir, glob, or array', {
|
75
|
ignored: /(^|[\/\\])\../,
|
76
|
persistent: true
|
77
|
});
|
78
|
|
79
|
// Something to use when events are received.
|
80
|
var log = console.log.bind(console);
|
81
|
// Add event listeners.
|
82
|
watcher
|
83
|
.on('add', path => log(`File ${path} has been added`))
|
84
|
.on('change', path => log(`File ${path} has been changed`))
|
85
|
.on('unlink', path => log(`File ${path} has been removed`));
|
86
|
|
87
|
// More possible events.
|
88
|
watcher
|
89
|
.on('addDir', path => log(`Directory ${path} has been added`))
|
90
|
.on('unlinkDir', path => log(`Directory ${path} has been removed`))
|
91
|
.on('error', error => log(`Watcher error: ${error}`))
|
92
|
.on('ready', () => log('Initial scan complete. Ready for changes'))
|
93
|
.on('raw', (event, path, details) => {
|
94
|
log('Raw event info:', event, path, details);
|
95
|
});
|
96
|
|
97
|
// 'add', 'addDir' and 'change' events also receive stat() results as second
|
98
|
// argument when available: http://nodejs.org/api/fs.html#fs_class_fs_stats
|
99
|
watcher.on('change', (path, stats) => {
|
100
|
if (stats) console.log(`File ${path} changed size to ${stats.size}`);
|
101
|
});
|
102
|
|
103
|
// Watch new files.
|
104
|
watcher.add('new-file');
|
105
|
watcher.add(['new-file-2', 'new-file-3', '**/other-file*']);
|
106
|
|
107
|
// Get list of actual paths being watched on the filesystem
|
108
|
var watchedPaths = watcher.getWatched();
|
109
|
|
110
|
// Un-watch some files.
|
111
|
watcher.unwatch('new-file*');
|
112
|
|
113
|
// Stop watching.
|
114
|
watcher.close();
|
115
|
|
116
|
// Full list of options. See below for descriptions. (do not use this example)
|
117
|
chokidar.watch('file', {
|
118
|
persistent: true,
|
119
|
|
120
|
ignored: '*.txt',
|
121
|
ignoreInitial: false,
|
122
|
followSymlinks: true,
|
123
|
cwd: '.',
|
124
|
disableGlobbing: false,
|
125
|
|
126
|
usePolling: true,
|
127
|
interval: 100,
|
128
|
binaryInterval: 300,
|
129
|
alwaysStat: false,
|
130
|
depth: 99,
|
131
|
awaitWriteFinish: {
|
132
|
stabilityThreshold: 2000,
|
133
|
pollInterval: 100
|
134
|
},
|
135
|
|
136
|
ignorePermissionErrors: false,
|
137
|
atomic: true // or a custom 'atomicity delay', in milliseconds (default 100)
|
138
|
});
|
139
|
|
140
|
```
|
141
|
|
142
|
## API
|
143
|
|
144
|
`chokidar.watch(paths, [options])`
|
145
|
|
146
|
* `paths` (string or array of strings). Paths to files, dirs to be watched
|
147
|
recursively, or glob patterns.
|
148
|
* `options` (object) Options object as defined below:
|
149
|
|
150
|
#### Persistence
|
151
|
|
152
|
* `persistent` (default: `true`). Indicates whether the process
|
153
|
should continue to run as long as files are being watched. If set to
|
154
|
`false` when using `fsevents` to watch, no more events will be emitted
|
155
|
after `ready`, even if the process continues to run.
|
156
|
|
157
|
#### Path filtering
|
158
|
|
159
|
* `ignored` ([anymatch](https://github.com/es128/anymatch)-compatible definition)
|
160
|
Defines files/paths to be ignored. The whole relative or absolute path is
|
161
|
tested, not just filename. If a function with two arguments is provided, it
|
162
|
gets called twice per path - once with a single argument (the path), second
|
163
|
time with two arguments (the path and the
|
164
|
[`fs.Stats`](http://nodejs.org/api/fs.html#fs_class_fs_stats)
|
165
|
object of that path).
|
166
|
* `ignoreInitial` (default: `false`). If set to `false` then `add`/`addDir` events are also emitted for matching paths while
|
167
|
instantiating the watching as chokidar discovers these file paths (before the `ready` event).
|
168
|
* `followSymlinks` (default: `true`). When `false`, only the
|
169
|
symlinks themselves will be watched for changes instead of following
|
170
|
the link references and bubbling events through the link's path.
|
171
|
* `cwd` (no default). The base directory from which watch `paths` are to be
|
172
|
derived. Paths emitted with events will be relative to this.
|
173
|
* `disableGlobbing` (default: `false`). If set to `true` then the strings passed to `.watch()` and `.add()` are treated as
|
174
|
literal path names, even if they look like globs.
|
175
|
|
176
|
#### Performance
|
177
|
|
178
|
* `usePolling` (default: `false`).
|
179
|
Whether to use fs.watchFile (backed by polling), or fs.watch. If polling
|
180
|
leads to high CPU utilization, consider setting this to `false`. It is
|
181
|
typically necessary to **set this to `true` to successfully watch files over
|
182
|
a network**, and it may be necessary to successfully watch files in other
|
183
|
non-standard situations. Setting to `true` explicitly on MacOS overrides the
|
184
|
`useFsEvents` default. You may also set the CHOKIDAR_USEPOLLING env variable
|
185
|
to true (1) or false (0) in order to override this option.
|
186
|
* _Polling-specific settings_ (effective when `usePolling: true`)
|
187
|
* `interval` (default: `100`). Interval of file system polling. You may also
|
188
|
set the CHOKIDAR_INTERVAL env variable to override this option.
|
189
|
* `binaryInterval` (default: `300`). Interval of file system
|
190
|
polling for binary files.
|
191
|
([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
|
192
|
* `useFsEvents` (default: `true` on MacOS). Whether to use the
|
193
|
`fsevents` watching interface if available. When set to `true` explicitly
|
194
|
and `fsevents` is available this supercedes the `usePolling` setting. When
|
195
|
set to `false` on MacOS, `usePolling: true` becomes the default.
|
196
|
* `alwaysStat` (default: `false`). If relying upon the
|
197
|
[`fs.Stats`](http://nodejs.org/api/fs.html#fs_class_fs_stats)
|
198
|
object that may get passed with `add`, `addDir`, and `change` events, set
|
199
|
this to `true` to ensure it is provided even in cases where it wasn't
|
200
|
already available from the underlying watch events.
|
201
|
* `depth` (default: `undefined`). If set, limits how many levels of
|
202
|
subdirectories will be traversed.
|
203
|
* `awaitWriteFinish` (default: `false`).
|
204
|
By default, the `add` event will fire when a file first appears on disk, before
|
205
|
the entire file has been written. Furthermore, in some cases some `change`
|
206
|
events will be emitted while the file is being written. In some cases,
|
207
|
especially when watching for large files there will be a need to wait for the
|
208
|
write operation to finish before responding to a file creation or modification.
|
209
|
Setting `awaitWriteFinish` to `true` (or a truthy value) will poll file size,
|
210
|
holding its `add` and `change` events until the size does not change for a
|
211
|
configurable amount of time. The appropriate duration setting is heavily
|
212
|
dependent on the OS and hardware. For accurate detection this parameter should
|
213
|
be relatively high, making file watching much less responsive.
|
214
|
Use with caution.
|
215
|
* *`options.awaitWriteFinish` can be set to an object in order to adjust
|
216
|
timing params:*
|
217
|
* `awaitWriteFinish.stabilityThreshold` (default: 2000). Amount of time in
|
218
|
milliseconds for a file size to remain constant before emitting its event.
|
219
|
* `awaitWriteFinish.pollInterval` (default: 100). File size polling interval.
|
220
|
|
221
|
#### Errors
|
222
|
* `ignorePermissionErrors` (default: `false`). Indicates whether to watch files
|
223
|
that don't have read permissions if possible. If watching fails due to `EPERM`
|
224
|
or `EACCES` with this set to `true`, the errors will be suppressed silently.
|
225
|
* `atomic` (default: `true` if `useFsEvents` and `usePolling` are `false`).
|
226
|
Automatically filters out artifacts that occur when using editors that use
|
227
|
"atomic writes" instead of writing directly to the source file. If a file is
|
228
|
re-added within 100 ms of being deleted, Chokidar emits a `change` event
|
229
|
rather than `unlink` then `add`. If the default of 100 ms does not work well
|
230
|
for you, you can override it by setting `atomic` to a custom value, in
|
231
|
milliseconds.
|
232
|
|
233
|
### Methods & Events
|
234
|
|
235
|
`chokidar.watch()` produces an instance of `FSWatcher`. Methods of `FSWatcher`:
|
236
|
|
237
|
* `.add(path / paths)`: Add files, directories, or glob patterns for tracking.
|
238
|
Takes an array of strings or just one string.
|
239
|
* `.on(event, callback)`: Listen for an FS event.
|
240
|
Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`,
|
241
|
`raw`, `error`.
|
242
|
Additionally `all` is available which gets emitted with the underlying event
|
243
|
name and path for every event other than `ready`, `raw`, and `error`.
|
244
|
* `.unwatch(path / paths)`: Stop watching files, directories, or glob patterns.
|
245
|
Takes an array of strings or just one string.
|
246
|
* `.close()`: Removes all listeners from watched files.
|
247
|
* `.getWatched()`: Returns an object representing all the paths on the file
|
248
|
system being watched by this `FSWatcher` instance. The object's keys are all the
|
249
|
directories (using absolute paths unless the `cwd` option was used), and the
|
250
|
values are arrays of the names of the items contained in each directory.
|
251
|
|
252
|
## CLI
|
253
|
|
254
|
If you need a CLI interface for your file watching, check out
|
255
|
[chokidar-cli](https://github.com/kimmobrunfeldt/chokidar-cli), allowing you to
|
256
|
execute a command on each change, or get a stdio stream of change events.
|
257
|
|
258
|
## Install Troubleshooting
|
259
|
|
260
|
* `npm WARN optional dep failed, continuing fsevents@n.n.n`
|
261
|
* This message is normal part of how `npm` handles optional dependencies and is
|
262
|
not indicative of a problem. Even if accompanied by other related error messages,
|
263
|
Chokidar should function properly.
|
264
|
|
265
|
* `ERR! stack Error: Python executable "python" is v3.4.1, which is not supported by gyp.`
|
266
|
* You should be able to resolve this by installing python 2.7 and running:
|
267
|
`npm config set python python2.7`
|
268
|
|
269
|
* `gyp ERR! stack Error: not found: make`
|
270
|
* On Mac, install the XCode command-line tools
|
271
|
|
272
|
## License
|
273
|
|
274
|
The MIT License (MIT)
|
275
|
|
276
|
Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com) & Elan Shanker
|
277
|
|
278
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
279
|
of this software and associated documentation files (the “Software”), to deal
|
280
|
in the Software without restriction, including without limitation the rights
|
281
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
282
|
copies of the Software, and to permit persons to whom the Software is
|
283
|
furnished to do so, subject to the following conditions:
|
284
|
|
285
|
The above copyright notice and this permission notice shall be included in
|
286
|
all copies or substantial portions of the Software.
|
287
|
|
288
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
289
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
290
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
291
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
292
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
293
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
294
|
THE SOFTWARE.
|