This article was last updated on November 8, 2024 to include advanced Nodemon configurations and best practices for handling memory management in long-running processes.
Update: Enhanced Watch Mode in Node.js Version 22
One of the standout features in the latest release of Node.js, version 22, is the improved watch mode. This feature is now considered stable, which means it's no longer experimental and can be relied upon for regular use.
Watch mode simplifies developers' lives by automatically restarting the Node.js process whenever it detects changes in the files being monitored. This is particularly useful if you're working on large projects where manual restarts can be tedious and time-consuming.
Previously, developers might have used tools like Nodemon and Watchman to manage file changes, especially on Windows, where detecting these changes could be challenging. Watch mode offers a more integrated and straightforward approach, eliminating the need for external tools and streamlining the development process.
By using watch mode, you no longer need to manually restart your server or tools like Nodemon after making changes to your code. This saves time and allows you to see the effects of your changes immediately, making your development workflow much more efficient.
Introduction
As a developer, you know how tedious it is to restart the application every time you tweak the code. Nodemon eliminates this hassle by automatically restarting the app whenever any change is detected. It's incredibly helpful as it lets you concentrate on coding without interruption.
Nodemon watches the files in your project and instantly applies updates by restarting your app—no more manual resets. This has noticeably sped up my development process, making it smoother and more productive. It’s especially crucial in a fast-paced work environment where every second counts.
Steps we'll cover in this guide:
- Installing Nodemon
- Using Nodemon
- Advanced Configuration
- Using Nodemon inside Docker Containers
- Memory Leak Handling in Longer Running Nodemon Processes
Installing Nodemon
I just went through setting up Nodemon. You install it using npm, the Node.js package manager. Just open your terminal and type:
npm install -g nodemon
This installs Nodemon globally on your system, so you can use it for any project. To make sure it's installed correctly, you can check its version with:
nodemon --version
If it shows the version, you're all set! Nodemon will now automatically restart your Node.js applications whenever you make changes. It’s a real time-saver, making it smoother to develop without breaking your flow.
Using Nodemon
Here's a simple Express.js application example using Nodemon:
// 1. First, install the Express.js and Nodemon modules
const express = require("express");
const app = express();
// 2. Define a simple endpoint to listen for HTTP requests
app.get("/", (req, res) => {
res.send("Hello, World!");
});
// 3. Start listening for the application on a specific port
const port = 3000;
app.listen(port, () => {
console.log(`Server successfully connected to port ${port}.`);
});
This represents a basic Express.js application. The main file can be named app.js
, for example. Now let's demonstrate how to use Nodemon to automatically restart this application.
First, make sure you're in your project directory where your Node.js application, like an Express.js app, is located.
- Install Express.js and Nodemon if you haven’t already.
npm install express nodemon
- After installing Nodemon, using it to automatically restart your Node.js apps is simple. Navigate to the directory where your Node.js application is located using the terminal or command prompt. Once you're in the project directory, you can start your Node.js application with Nodemon by typing:
nodemon app.js
This command fires up your application with Nodemon, so it automatically restarts whenever you change any files. For instance, if you update the response in your app.js
from 'Hello, World!' to something else and save, Nodemon immediately restarts and applies the update without you needing to do anything.
Also, here’s what you typically see in the terminal when you start:
[nodemon] 2.0.15
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,json
[nodemon] starting `node app.js`
Server successfully connected to port 3000.
It shows Nodemon is watching all your files and is ready to restart anytime you make edits.
In this output:
[nodemon] 2.0.15
: This indicates the version of Nodemon being used.[nodemon] to restart at any time, enter 'rs'
: This message informs you that you can manually restart the application at any time by entering 'rs' in the terminal.[nodemon] watching path(s): *.*
: Nodemon is watching for changes in all files and directories.[nodemon] watching extensions: js,json
: Nodemon is specifically watching for changes in JavaScript and JSON files.[nodemon] starting 'node app.js'
: Nodemon is starting the Node.js application (app.js
in this case).Server successfully connected to port 3000.
: This message indicates that the Express.js server has successfully started and is listening on port 3000.
Advanced Configuration
I’ve been diving deeper into Nodemon’s capabilities and found some cool ways to customize its behavior to better suit our projects. Nodemon allows you to tailor its restart rules according to our specific needs, which is super handy.
Here’s a breakdown:
File Watch Patterns: You can set Nodemon to watch only specific directories. This is great because it lets us focus on crucial parts of our project without getting distracted by unnecessary restarts.
For instance, if you only want to watch the
src
andconfig
directories, your config would look like this:{
"watch": ["src", "config"]
}Ignore Patterns: We can also tell Nodemon to ignore certain directories that don’t impact our app’s functionality, like log files or public assets. This means Nodemon won’t restart when changes occur in these areas.
Here’s how you could set it up to ignore the
logs
andpublic
directories:{
"ignore": ["logs", "public"]
}Delaying Restarts: If rapid successive changes are causing too many restarts, we can introduce a delay. This gives us a buffer after making changes before Nodemon restarts the app, helping stabilize our development environment.
For adding a one-second delay, you’d configure it like this:
{
"delay": 1000
}
These tweaks have made a noticeable difference in managing the development flow, especially in complex projects. I think implementing these could really streamline how we handle automatic restarts in our development process!
Using Nodemon inside Docker Containers
I wanted to share this tutorial on how one integrates Nodemon with Docker, which turns out to be a game-changing setup when using Node.js applications running in Docker containers. This will allow it inside the Docker to, automatically restart the application in the container whenever changes are made to the code.
Why Use Nodemon with Docker?
One of the most important advantages of developing in Docker containers is that we usually rebuild or restart the container for every change in the code, which really takes a lot of time. This step can be skipped by integrating Nodemon and letting Nodemon watch the changes in files and restart on its own inside the container.
Setting up Nodemon with Docker
To use Nodemon inside a Docker container, we will add Nodemon in our project and make some changes to the Docker configuration. Here is how you can do this step by step:
Integrate Nodemon into the Project
First, ensure Nodemon is installed within the project:
npm install --save-dev nodemon
Dockerfile Update for Nodemon Next, in Dockerfile, set Nodemon as a command to start our app. Here’s a basic example:
FROM node:14
# Set working directory
WORKDIR /app
# copy package.json and install dependencies
COPY package*.json ./
RUN npm install
# Copy the rest of the application
COPY . .
# Require Nodemon installation globally
RUN npm install -g nodemon
# Expose the required port
EXPOSURE 3000
# Nodemon as default run command
CMD ["nodemon", "app.js"]
Create a Volume for Live Reloading In Docker, we will use volumes, so changes made to the files from our host machine reflect inside the container. By doing so, Nodemon will be able to detect real-time file change. Here’s an example docker-compose.yml file to set that up:
version: "3"
services:
app:
build: .
volumes:
- .:/app # Mount current directory to /app in the container
- /app/node_modules # Avoids conflicts with the host node_modules
ports:
- "3000:3000"
command: nodemon app.js
Running a Container
Everything should now be set. Start your container:
docker-compose up
This setup will allow you to make changes to the code on your local machine, which are instantly reflected inside the container because of the volume mount; then Nodemon will detect these changes and restart the application automatically.
Basic Troubleshooting Tips
- Permissions Issues: Sometimes on some systems, file permissions can be why Nodemon does not detect changes. You might want to change permissions or run Docker as root if this exists.
- Conflicting node_modules: Remember, while working with docker-compose.yml the application’s node_modules should not be part of the volume mount. If different, this causes conflict between the host and container.
Memory Leak Handling in Longer Running Nodemon Processes
We would especially want to control the consumption of memory for applications that run continually through Nodemon during development. While Nodemon is great at watching and attempting to restart our application upon file changes, should it not be watched, a long-running Nodemon process can leak memory until eventually performance degrades and the app crashes. Following is how we could handle such a memory leak.
Why memory leaks happen in long-running Nodemon processes
Memory leaks happen when, through our application, we keep references to data that is no longer needed and that prevents JavaScript’s garbage collector from freeing up the memory. In a development process that could run for a longer period of time, Nodemon might take up more and more memory over time due to repeated file changes, event listeners, or unoptimized code.
Prevention strategies for memory leaks using Nodemon
Memory Consumption Monitoring
Use Node.js’s built-in memory monitoring to observe memory usage. Insert this into your code and log memory usage at regular intervals:
setInterval(() => {
const memoryUsage = process.memoryUsage();
console.log(`Memory Usage: RSS ${memoryUsage.rss / 1024 / 1024} MB`);
}, 10000); // log memory usage every 10 seconds
Limit Frequency of Restarts
Not allowing the system time to clean up resources can cause a memory buildup with rapid restarts. To delay the restarts so the system can clear its memory, use the --delay flag inside of Nodemon:
nodemon --delay 2 app.js
Watch PATHS Optimizations
Avoid watching unnecessary files or directories to save on memory consumption. Example - you would likely want to exclude files like logs or static assets:
{
"watch": ["src"],
"ignore": ["logs/*", "public/*"]
}
Identify and Optimize Code-related Leaks
Identify unwanted listeners or event handlers not cleaned up. Usually, these are the most common sources of Node.js memory leaks. Use tools such as clinic.js or Chrome DevTools to trace heap snapshots and have detailed inspections of memory consumption.
Periodic Restart If it is still not enough and memory consumption remains a problem, periodic restarts of Nodemon will clean up its memory usage, too. Use a process manager like pm2 to schedule this:
pm2 start nodemon --name "app" -- app.js --max-memory-restart 200M
These practices will help us to keep our development process smooth, even during long-running sessions with Nodemon. Feel free to let me know if you’d like to discuss setting up memory monitoring or provide a finger in the direction on how parts of this code could be optimized.
Conclusion
As we wrap up discussing Nodemon, I wanted to share some common issues you might run into and how to troubleshoot them. Even though Nodemon simplifies our development by auto-restarting our apps, sometimes it might not work as expected.
Here are a few things to check if you encounter problems:
Monitoring Files: If Nodemon isn't restarting when you change files, double-check your configuration to ensure it’s watching the right files and directories. Sometimes, if we ignore too many files, Nodemon might miss changes in crucial areas.
Crashes or Non-starts: Make sure there are no errors in your Node.js app and that all environment variables are set correctly. These can often stop Nodemon from running properly.
Permissions on Windows: If you’re on Windows and facing permission issues, try running Nodemon in an administrator command prompt, which can resolve these problems.
Software Updates: Lastly, keeping Nodemon and Node.js updated to their latest versions can solve a lot of known issues.