node --watch: restart the app when a file changes (no nodemon)
- tool
- Node.js
- command
- node
- flag
- --watch, --watch-path=PATH, --watch-preserve-output
- default
- off
- since
- 18.11.0
node --watch app.js runs the script and restarts it every time the entry file or any module it imported changes on disk. It is built into Node.js since 18.11.0 (stable since 22.0.0 and 20.13.0), so the nodemon package is no longer needed for the usual "restart the server on save" workflow. By default Node.js clears the console on each restart; --watch-preserve-output keeps the previous output.
Restart on change
The script prints a line; one second later the block edits it, and --watch reruns it. timeout stops the watcher after four seconds (exit code 124):
cat > app.js <<'EOF'
console.log("version 1");
EOF
(sleep 1.5; echo 'console.log("version 2");' > app.js) &
timeout 4 node --watch --watch-preserve-output app.jsOutput · exit 124
version 1 Completed running 'app.js'. Waiting for file changes before restarting... Change detected in '/tmp/work/app.js' Restarting 'app.js' version 2 Completed running 'app.js'. Waiting for file changes before restarting...
When the program exits on its own, Node.js prints Completed running 'app.js' and keeps waiting; when a long-running server is restarted, the old process is stopped first, so the port is free for the new one.
Related flags
| Flag | Effect |
|---|---|
| --watch | Watch the entry point and every required or imported module |
| --watch-path=DIR | Watch only the given paths (repeatable); turns off watching of imported modules |
| --watch-preserve-output | Do not clear the console when restarting |
| --watch-kill-signal=SIGNAL | Signal sent to the old process on restart (default SIGTERM; newer releases only) |
| --env-file=.env | Can be combined with --watch to load variables on every start |
--watch-path is useful when the program reads files at runtime (templates, JSON, SQL) that are never imported: node --watch-path=./src --watch-path=./views server.js. Note that it replaces the module tracking instead of adding to it.
In package.json
{
"scripts": {
"dev": "node --watch --env-file=.env src/server.js",
"start": "node src/server.js"
}
}Keep --watch out of the production start script: it adds file system watchers and restarts the process when a deploy writes files.
Pitfalls and limits
--watchcannot be combined with--check,--eval,--interactiveor the REPL; it needs a script file.- In watch mode Node.js waits for the old process to exit. A server that ignores
SIGTERMdelays every restart. - On network shares, some containers and WSL mounts of Windows folders, file change events may not arrive; editing inside the container's own file system or using a polling watcher such as nodemon's legacy mode helps.
- Older releases that only had
--watchas experimental print anExperimentalWarning; it is harmless. --watch-pathis not supported on every platform in older releases (it needs recursivefs.watch, which Linux gained in Node.js 20).
For TypeScript, combine the flag with type stripping: see run a TypeScript file with Node.js.
FAQ
Which files does node --watch watch?
The entry point and every module it loaded through require or import. Files read at runtime with fs.readFile, such as JSON configs or templates, are not watched unless you add them with --watch-path.
Does node --watch work with --env-file?
Yes, both flags can be combined (node --watch --env-file=.env app.js). Newer Node.js releases also restart when the .env file itself changes; on older ones, restart manually after editing it.
Is node --watch a replacement for nodemon?
For the common case of restarting a server on save, yes. nodemon still offers more: watching by extension, ignore patterns, delays and running non-Node commands.