chokidar-cli、grunt-contrib-watch、gulp-watch、nodemon、onchange、watch はすべてファイルシステムの変更を検知し、指定されたコマンドやタスクを自動実行するためのツールです。これらは主に開発ワークフローの自動化(例:再ビルド、テスト実行、サーバー再起動)に使われますが、それぞれが異なるエコシステムやユースケースを前提として設計されています。たとえば nodemon はNode.jsアプリケーションの再起動に特化しており、gulp-watch はGulpのストリームベースのパイプラインと密接に連携します。一方、chokidar-cli や onchange は汎用的なCLIツールとして、任意のシェルコマンドをトリガーできます。
フロントエンド開発において、ファイル変更を検知して自動でビルドやテストを走らせるのは日常茶飯事です。しかし「監視ツール」と一言で言っても、それぞれが異なる設計思想と制約を持っています。この記事では、6つの主要npmパッケージを実際のコードとともに比較し、どの場面でどれを選ぶべきかを明確にします。
chokidar-cliChokidarライブラリをラップしたCLIで、Globパターンと除外ルールを柔軟に指定できます。
# src/以下の.jsファイルを監視し、変更時にビルドスクリプトを実行
chokidar "src/**/*.js" -c "npm run build"
# 複数パターンと除外
chokidar "src/**/*" "test/**/*" -i "**/*.log" -c "echo changed"
grunt-contrib-watchGruntのタスクとして定義され、Gruntfile内で監視ルールを記述します。
// Gruntfile.js
grunt.initConfig({
watch: {
scripts: {
files: ['src/**/*.js'],
tasks: ['babel', 'uglify']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
⚠️ 注意: Grunt自体が現代の開発フローではほとんど使われておらず、このプラグインも積極的なメンテナンスが確認できません。新規プロジェクトでの使用は非推奨です。
gulp-watchGulpのストリームに直接組み込まれ、パイプラインの一部として動作します。
// gulpfile.js
const watch = require('gulp-watch');
const babel = require('gulp-babel');
gulp.task('scripts', () => {
return watch('src/**/*.js')
.pipe(babel())
.pipe(gulp.dest('dist'));
});
nodemonNode.jsアプリケーションの再起動に特化。メインファイルの変更を検知してプロセスを再起動します。
# server.jsの変更を監視して再起動
nodemon server.js
# 設定ファイルで詳細制御
nodemon --config nodemon.json
// nodemon.json
{
"watch": ["src/", "config/"],
"ext": "js,json",
"ignore": ["src/**/*.test.js"]
}
onchangeシンプルなCLI構文で、直感的に使えるのが特徴です。
# src/以下の.jsファイル変更時にビルド
onchange "src/**/*.js" -- npm run build
# 複数パターン
onchange "src/**/*" "public/**/*" -- echo "File changed"
watch古くからある汎用CLIですが、内部実装が時代遅れです。
# 基本的な使い方
watch "npm test" src/
⚠️ 注意: このパッケージは非推奨の
gazeライブラリに依存しており、最新OSでの信頼性に問題があります。新規プロジェクトでは使用しないでください。
chokidar-cli: -i オプションで除外パターンを指定可能。--initial で起動時にもコマンドを実行。
chokidar "src/**/*" -i "**/*.tmp" -c "build"
nodemon: ignore 配列で除外、watch で監視ディレクトリを限定。拡張子フィルタ (ext) もサポート。
{ "ignore": ["*.log", ".git/**"], "ext": "js,ts,json" }
onchange: Globパターンのみでフィルタリング。除外機能はなし。
onchange "src/!(temp)/*.js" -- build
gulp-watch: Gulpの通常のsrc指定と同様にGlobが使えるが、除外は別途 gulp-ignore などが必要。
連続変更に対する過剰な実行を防ぐため、多くのツールが遅延機能を提供します。
chokidar-cli: -d または --delay オプション(ミリ秒単位)
chokidar "src/**/*" -d 1000 -c "build"
nodemon: --delay オプション(秒単位、小数可)
nodemon --delay 1.5 server.js
onchange: --wait オプション(ミリ秒)
onchange "src/**/*" --wait 500 -- build
gulp-watch: 第二引数でオプション指定
watch('src/**/*', { delay: 500 }, cb => { /* ... */ })
nodemon: events セクションで再起動前後などのフックを定義可能。
{
"events": {
"start": "echo app starting",
"restart": "echo app restarted"
}
}
chokidar-cli: コマンド実行以外のフックはサポートされていません。
gulp-watch: ストリームイベント(add, change, unlink)を個別にハンドリング可能。
watch('src/**/*')
.on('change', path => console.log(`${path} changed`))
.pipe(/* ... */);
nodemonnodemon --inspect src/server.js
chokidar-cli または onchangechokidar-cli は除外ルールが必要な場合に、onchange はシンプルさが欲しい場合に。# chokidar-cli(除外あり)
chokidar "src/**/*" -i "**/*.bak" -c "tsc"
# onchange(シンプル)
onchange "src/**/*" -- tsc
gulp-watch// gulpfile.js
watch('src/styles/*.scss')
.pipe(sass())
.pipe(gulp.dest('dist/css'));
grunt-contrib-watch はメンテナンスされていない可能性が高い。移行を検討すべき。chokidar-cliwatch: 内部で gaze を使用しており、これはすでに非推奨です。macOSのAPFSやWindowsの最新ファイルシステムでイベントを見逃すことがあります。代わりにChokidarベースのツール(chokidar-cli や onchange)を使用してください。
grunt-contrib-watch: Gruntエコシステム全体が衰退傾向にあり、このプラグインの更新も長期間停止しています。新規プロジェクトではGrunt自体を避けるべきです。
| パッケージ | 監視エンジン | Globサポート | 除外ルール | 遅延実行 | イベントフック | 推奨用途 |
|---|---|---|---|---|---|---|
chokidar-cli | Chokidar | ✅ | ✅ (-i) | ✅ (-d) | ❌ | 汎用CLI監視、CI環境 |
grunt-contrib-watch | gaze (非推奨) | ✅ | ✅ | ✅ | ❌ | 非推奨(Gruntレガシー) |
gulp-watch | Chokidar | ✅ | △(別プラグイン) | ✅ | ✅(ストリームイベント) | Gulp統合 |
nodemon | Chokidar | ✅ | ✅ | ✅ | ✅ | Node.jsサーバー開発 |
onchange | Chokidar | ✅ | ❌ | ✅ (--wait) | ❌ | シンプルなワンライナー監視 |
watch | gaze (非推奨) | ❌ | ❌ | ❌ | ❌ | 非推奨 |
nodemon を使う — これ以上シンプルで効果的な選択肢はありません。gulp-watch を使う — 他のツールだとワークフローが壊れます。chokidar-cli か onchange — 除外ルールが必要なら前者、とにかく簡単さが欲しいなら後者。watch と grunt-contrib-watch — 信頼性とメンテナンス性の観点から、新規プロジェクトでは使ってはいけません。これらのツールはどれも「ファイルが変わったら何かする」という同じ目的を持っていますが、その周辺の制約や機能が大きく異なります。自分のプロジェクトの技術スタックと要件に合わせて、適切な1つを選びましょう。
chokidar-cli は、Chokidarライブラリを直接利用したシンプルで高速なCLIツールです。任意のファイルパターンを監視し、変更時に任意のコマンドを実行できます。Globパターンや除外ルールのサポートが充実しており、ビルドスクリプトやカスタムワークフローに組み込むのに適しています。GruntやGulpのようなビルドツールを使わず、軽量な監視機能だけが必要な場合に最適です。
grunt-contrib-watch はGruntエコシステム内で動作するプラグインです。Gruntfileで定義されたタスクをファイル変更時に再実行します。ただし、Grunt自体が現代のフロントエンド開発ではあまり使われなくなっており、このパッケージもメンテナンスが停滞しています。新規プロジェクトでGruntを使っていない限り、選択すべきではありません。
gulp-watch はGulpのストリーム処理と統合された監視プラグインです。Gulpのパイプライン内でファイル変更を検知し、後続の処理(例:コンパイル、圧縮)をトリガーできます。Gulpベースのビルドシステムをすでに採用しているプロジェクトでは自然な選択肢ですが、Gulpを使わない環境ではオーバーヘッドになります。
nodemon はNode.jsアプリケーションの開発に特化した監視ツールです。メインエントリーファイル(例:server.js)の変更を検知してプロセスを自動再起動します。設定ファイル(nodemon.json)による詳細なカスタマイズや、遅延再起動、イベントフックなどの機能を備えています。ExpressやFastifyなど、Node.jsサーバー開発を行う場合はまず検討すべきツールです。
onchange はシンプルで直感的なCLIベースの監視ツールです。Globパターンでファイルを指定し、変更時に任意のコマンドを実行できます。構文が非常に分かりやすく、ワンライナーでの使用に向いています。複雑な設定や高度なフィルタリングが不要な場合、素早く導入できる点が魅力です。
watch パッケージは古くからある汎用監視CLIですが、内部で非推奨の gaze ライブラリを使用しており、現代のファイルシステムイベント(特にmacOSやWindows)への対応が不十分です。Chokidarベースの代替ツールが多数存在するため、新規プロジェクトでは使用を避けるべきです。
Fast cross-platform command line utility to watch file system changes.
The underlying watch library is Chokidar, which is one of the best watch utilities for Node. Chokidar is battle-tested:
It is used in brunch, gulp, karma, PM2, browserify, webpack, BrowserSync, socketstream, derby, and many others. It has proven itself in production environments.
If you need it only with npm scripts:
npm install chokidar-cli
Or globally
npm install -g chokidar-cli
Chokidar can be invoked using the chokidar command, without the -cli suffix.
Arguments use the form of runtime flags with string parameters, delimited by quotes. While in principal both single and double quotes are supported by chokidar-cli, the actual command line argument parsing is dependent on the operating system and shell used; for cross-platform compatibility, use double quotes (with escaping, if necessary), as single quotes are not universally supported by all operating systems.
This is particularly important when using chokidar-cli for run scripts specified in package.json. For maximum platform compatibility, make sure to use escaped double quotes around chokidar's parameters:
"run": {
"chokidar": "chokidar \"**/*.js\" -c \"...\""
},
By default chokidar streams changes for all patterns to stdout:
$ chokidar "**/*.js" "**/*.less"
change:test/dir/a.js
change:test/dir/a.less
add:test/b.js
unlink:test/b.js
Each change is represented with format event:relativepath. Possible events: add, unlink, addDir, unlinkDir, change.
Output only relative paths on each change
$ chokidar "**/*.js" "**/*.less" | cut -d ":" -f 2-
test/dir/a.js
test/dir/a.less
test/b.js
test/b.js
Run npm run build-js whenever any .js file changes in the current work directory tree
chokidar "**/*.js" -c "npm run build-js"
Watching in network directories must use polling
chokidar "**/*.less" -c "npm run build-less" --polling
Pass the path and event details in to your custom command
chokidar "**/*.less" -c "if [ '{event}' = 'change' ]; then npm run build-less -- {path}; fi;"
Detailed help
Usage: chokidar <pattern> [<pattern>...] [options]
<pattern>:
Glob pattern to specify files to be watched.
Multiple patterns can be watched by separating patterns with spaces.
To prevent shell globbing, write pattern inside quotes.
Guide to globs: https://github.com/isaacs/node-glob#glob-primer
Options:
-c, --command Command to run after each change. Needs to be
surrounded with quotes when command contains spaces.
Instances of `{path}` or `{event}` within the command
will be replaced by the corresponding values from the
chokidar event.
-d, --debounce Debounce timeout in ms for executing command
[default: 400]
-t, --throttle Throttle timeout in ms for executing command
[default: 0]
-s, --follow-symlinks When not set, only the symlinks themselves will be
watched for changes instead of following the link
references and bubbling events through the links path
[boolean] [default: false]
-i, --ignore Pattern for files which should be ignored. Needs to be
surrounded with quotes to prevent shell globbing. The
whole relative or absolute path is tested, not just
filename. Supports glob patterns or regexes using
format: /yourmatch/i
--initial When set, command is initially run once
[boolean] [default: false]
-p, --polling Whether to use fs.watchFile(backed by polling) instead
of fs.watch. This might lead to high CPU utilization.
It is typically necessary to set this to true to
successfully watch files over a network, and it may be
necessary to successfully watch files in other non-
standard situations [boolean] [default: false]
--poll-interval Interval of file system polling. Effective when --
polling is set [default: 100]
--poll-interval-binary Interval of file system polling for binary files.
Effective when --polling is set [default: 300]
--verbose When set, output is more verbose and human readable.
[boolean] [default: false]
--silent When set, internal messages of chokidar-cli won't be
written. [boolean] [default: false]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]
Examples:
chokidar "**/*.js" -c "npm run build-js" build when any .js file changes
chokidar "**/*.js" "**/*.less" output changes of .js and .less
files
MIT