How to use Nodemon to automatically restart Node.js applications

There's no need to manually stop and restart a running Node.js app whenever you update code.

Fast iteration is key to modern web development, but you must stop and restart Node.js applications every time you make a code change. The process can slow updates and debugging, but tools such as Nodemon can improve your workflow.

Why do Node.js applications need restarting?

Applications written in languages such as PHP do not need restarting when you update code. When you refresh your browser, it sends a request to a web server such as Apache or NGINX. The server parses the URL, identifies a PHP file, and passes its content to the PHP runtime interpreter. The PHP code runs, and the server receives the result, which it passes back to the browser.

In Node.js, your application is a web server. Running node myapp.js, loads the application, initializes, and starts a server, which can respond to incoming requests. Changing a file won't change the application because an earlier incarnation is running in memory. To test an update, you must shut it down using Ctrl | Cmd + C, re-run node myapp.js, and refresh the browser.

Note: An Apache or NGINX web server is often used as a reverse proxy for Node.js applications. This approach enhances security since the app does not need to run with elevated privileges (root access), and the server can return static assets without any JavaScript parsing.

Introducing Nodemon

Stopping and restarting a Node.js application becomes annoying when you're in the zone or debugging a complex problem. Nodemon is a Node.js tool developed by Remy Sharp that watches for file changes and restarts your app automatically. It saves vital seconds, which equate to hours over the course of developing an app!

Do you need for Nodemon? Node.js native watch mode

Node.js versions after 18.11 released in 2022 provide a --watch command line switch to watch for file changes and restart accordingly. There's no need to install a third-party module, and you can run an application directly:

node --watch myapp.js

You can set specific paths on Windows and MacOS using --watch-path:

node --watch-path=./lib --watch-path=./config myapp.js

Similar options are available in Deno:

deno run --watch myapp.js

and Bun:

bun --watch myapp.js

Native file --watch may be good enough for projects with simpler requirements, but it has disadvantages:

  • Limited functionality. --watch offers basic file monitoring and restarting, but it lacks advanced Nodemon features such as configuring output, handling crashes, running events, launching non-Node.js executables, and more.
  • Scalability issues. --watch will attempt to watch all files in a large project. This could become slow and it lacks Nodemon's ability to limit file types and locations.
  • Cross-platform limitations. Unlike Nodemon, --watch-path does not support wildcards and is only available on MacOS and Windows at the time of writing.

Perhaps use the native --watch command for your initial development needs, but transition to Nodemon for advanced functionality as your project grows.

Installing Nodemon

Installing Nodemon as a global module is the preferred method and ensures it's available in all projects. You can run nodemon on the command line from any directory:

npm install nodemon -g

You can also install Nodemon as a development dependency in a specific project. You won't be able to run nodemon from the command line, but you can call it from a package.json script or using npx nodemon:

npm install nodemon --save-dev

Nodemon usage

nodemon replaces node on the command line. Rather than running a script with node myapp.js, you use nodemon myapp.js. It supports all the node command-line switches and arguments you want to use, such as loading .env files and running the debugger:

nodemon --env-file=.env --inspect myapp.js

Your application starts as normal, but editing and saving a JavaScript file now stops and restarts it without further interaction. If necessary, you can force a restart by typing rs with a carriage return in the active Nodemon terminal.

Example output:

$ nodemon --env-file=.env --inspect myapp.js

[nodemon] 3.1.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node --env-file=.env --inspect myapp.js`
Debugger listening on ws://127.0.0.1:9229/172ba931-68a5-4172-b8b0-69cebb0a7786
For help, see: https://nodejs.org/en/docs/inspector
[nodemon] restarting due to changes...

Note: Nodemon restarts your server-side application but won't refresh a client-side web page. Tools such as Browsersync or LiveReload can do that for you.

The following sections describe further Nodemon options.

Passing arguments to your script

Nodemon processes arguments passed at the end of the command line; they are NOT forwarded to myapp.js:

nodemon --env-file=.env --inspect myapp.js 1 2 "three"

To ensure myapp.js can process those arguments using process.argv, add a double hyphen (--) between the script name and the first argument, e.g.

nodemon --env-file=.env --inspect myapp.js -- 1 2 "three"

Nodemon help

For Nodemon help, enter nodemon --help or nodemon --help options:

$ nodemon --help

  Usage: nodemon [options] [script.js] [args]

  Options:

  --config file ............ alternate nodemon.json config file to use
  -e, --ext ................ extensions to look for, ie. js,pug,hbs.
  -x, --exec app ........... execute script with "app", ie. -x "python -v".
  -w, --watch path ......... watch directory "path" or files. use once for
                             each directory or file to watch.
  -i, --ignore ............. ignore specific files or directories.
  -V, --verbose ............ show detail on what is causing restarts.
  -- <your args> ........... to tell nodemon stop slurping arguments.

  Note: if the script is omitted, nodemon will try to read "main" from
  package.json and without a nodemon.json, nodemon will monitor .js, .mjs, .coffee,
  .litcoffee, and .json by default.

  For advanced nodemon configuration use nodemon.json: nodemon --help config
  See also the sample: https://github.com/remy/nodemon/wiki/Sample-nodemon.json

  Examples:

  $ nodemon server.js
  $ nodemon -w ../foo server.js apparg1 apparg2
  $ nodemon --exec python app.py
  $ nodemon --exec "make build" -e "styl hbs"
  $ nodemon app.js -- --config # pass config to app.js

  All options are documented under: nodemon --help options

Nodemon advanced configuration

Simpler projects won't require further Nodemon configuration, but you can pass one or more arguments on the Nodemon command line or define defaults in JSON files:

  1. A "nodemonConfig" section in your project's package.json file.
  2. A local nodemon.json configuration file in the project directory.
  3. Or any JSON configuration file passed using nodemon --config <file> on the command line.

Nodemon command line switches use dash-case/kebab-case names, e.g. --legacy-watch. JSON settings use camelCase, e.g. "legacyWatch".

The following sections describe the most-used configuration options.

Legacy file watch (-L or --legacy-watch)

File watching can fail in mounted drive environments such as networks and containers (Docker) because Nodemon does not have direct access to the disk. Legacy watch uses polling to check whether files have changed. It's more reliable, but can be noticeably slower on large codebases. To switch to legacy watch on the command line:

nodemon --legacy-watch myapp.js

The same option defined in package.json or a configuration file:

{
  "legacyWatch": true
}

The default polling interval is 100 milliseconds, but you can change this using -P or --polling-interval, e.g.

nodemon --legacy-watch --polling-interval 200ms myapp.js

Or in a configuration file:

{
  "legacyWatch": true,
  "pollingInterval": 200
}

Delayed restarts (-d or --delay)

You're often updating more than one file during development, so Nodemon ensures all files have saved by waiting for one second before triggering a restart. You can configure the delay period, e.g., set three seconds:

nodemon --delay 3 myapp.js

or the same delay in milliseconds:

nodemon --delay 3000ms myapp.js

The same option defined in package.json or a configuration file assumes millisecond values:

{
  "delay": 3000
}

Watch specific directories and files (-w or --watch)

Nodemon watches for JavaScript file changes in the current project. You can set specific directories or include non-JavaScript files. The following command watches JavaScript files in lib or any of its subdirectories, as well as JSON files in config:

nodemon --watch lib config/*.json myapp.js

The same options defined in package.json or a configuration file:

{
  "watch": [
    "lib",
    "config/*.json"
  ]
}

Watch by file extension (--ext)

Nodemon can watch for changes on files of a specific type. For example, watch all mjs module files and ejs template files:

nodemon --ext "mjs,ejs" myapp.js

The same options defined in package.json or a configuration file:

{
  "ext": "mjs,ejs"
}

Ignore files (-i or --watch)

You can also choose to ignore whole directories, files, or wildcards. For example, watch JavaScript files in lib and JSON files in config, except files in lib/dev/ or config/dev.json:

nodemon --watch lib config/*.json --ignore lib/dev/* config/dev.json myapp.js

The same options defined in package.json or a configuration file:

{
  "watch": [
    "lib",
    "config/*.json"
  ]
  "ignore": [
    "lib/dev/*",
    "config/dev.json"
  ]
}

Switch directory (--cwd)

You can switch to a different directory before running your application. This may be practical if you have more than one app in the same project and do not want Nodemon to watch everything:

nodemon --cwd ./app1/ app1.js

The same option defined in package.json or a configuration file:

{
  "cwd": "./app1/"
}

Exit on crash (--exitcrash)

If your application fails to start or crashes during execution, Nodemon will continue to watch for file changes and restart when necessary. You can force Nodemon to stop on application errors:

nodemon --exitcrash ./app1/ app1.js

Less verbose output (-q or --quiet)

You can limit Nodemon output to show nothing except start and stop messages:

nodemon --quiet myapp.js

The same option defined in package.json or a configuration file:

{
  "quiet": true
}

More verbose output (-V or --verbose)

If you want to see more output, you can display verbose status and error messages:

nodemon --verbose myapp.js

The same option defined in package.json or a configuration file:

{
  "verbose": true
}

Disable color output (--no-colors)

You can remove color from output messages using:

nodemon --no-color myapp.js

The same option defined in package.json or a configuration file:

{
  "noColor": true
}

Event triggers

Nodemon can run executables when specific events occur:

  • start - the application started
  • restart - the application restarted
  • exit - the application exited cleanly
  • crash - the application crashed
  • config:update - nodemon configuration changed

You can specify scripts in your project's package.json or a configuration file. The following example sends data to a web server using a curl command when your application restarts:

{
  "events": {
    "restart": "curl -d 'app=myapp' -X POST http://mymonitor.com/"
  }
}

Launch non-Node.js executables

You can use Nodemon to launch, watch, and restart applications written in other languages. For example, to run a Perl script:

nodemon --exec "perl" app.pl

You can also define runtime lists in package.json or a configuration file to associate a file extension with a specific executable.

{
  "execMap": {
    "pl": "perl"
  }
}

Once defined, there's no need to use the --exec option on the command line:

nodemon app.pl

Graceful script termination

In some cases, you may want your application to finish a task before it shuts down. For example, it may be necessary to commit outstanding database transactions, close the connection, and run other clean-up operations.

Nodemon sends a SIGUSR2 signal to your application when it detects a file change. Your application can define an event handler for this signal that cleans up and terminates itself, e.g.

process.on('SIGUSR2', async () => {

  // clean up, close connections, etc.
  await preShutdown();

  // kill self when done
  process.kill(process.pid, 'SIGTERM');

});

Summary

Auto-restarting Node.js code is vital as your application grows in scale and complexity. The native --watch switch provides a good way to start if you're using Node.js 18.11 or above.

Consider migrating to Nodemon when you require more control. As well as the Nodemon options listed above, you can also pipe output to other processes, add it as a module to your own projects, spawn it as a child process, and launch it in Gulp or Grunt workflows.

Did you find this article valuable?

Support Craig Buckler's Web Tech Tutorials by becoming a sponsor. Any amount is appreciated!