nodejs-watch-folder-feature-image

How to watch folder for changes in Node.js

Have you ever got a task in which you build a service to listen or watch another project (folder). If there is an error, a notification will be thrown. In this tutorial, we’re gonna look at a way to solve this problem: watch a folder for changes in Node.js.

Related post: How to watch file for changes in Node.js

Overview

Watch folder for changes in Node.js

The problem is determined. So how to deal with it?

At first, getting the error is to read log file that is generated when running a project, to watch it for appearance or changes. Next, we should create a service working independently of the main project (that generates the log file).

Assume that the main project Performance will generate error.log file in logs folder everytime it throws an error.

So what we will do is watching the logs folder. If error.log appears, read the file, get the content, and delete that file.

This is the structure for our example:

nodejs-watch-folder-changes-project-structure

Way to watch folder for changes

How do we build a service to work for this process?
We can use fs.watch, fs.watchFile from Node.js fs module. But it has disadvantages:

  • trigger change event twice while modify & save only once
  • get notification when changing the file name, while only listen to file content update
  • not support subfolders
  • some errors on macOS

We’d like to introduce chokidar module to solve this problem. At the time of writting this tutorial, it has over 13 milion downloaded per week.

This is the overview of chokidar API:

const chokidar = require('chokidar');

// Initialize watcher.
const watcher = chokidar.watch('path/to/folder', { persistent: true });
 
// Add event listeners.
watcher
  .on('add', path => log(`File ${path} has been added`))
  .on('change', path => log(`File ${path} has been changed`))
  .on('unlink', path => log(`File ${path} has been removed`));
 
// More possible events.
watcher
  .on('addDir', path => log(`Directory ${path} has been added`))
  .on('unlinkDir', path => log(`Directory ${path} has been removed`))
  .on('error', error => log(`Watcher error: ${error}`))
  .on('ready', () => log('Initial scan complete. Ready for changes'))

Practice

Setup Node.js modules

We need to install 2 packages: chokidar and fs-extra (promise support to the fs methods).
So run the command:
npm install chokidar fs-extra

Create Service for watching folder

Under services folder, create obserser.js file:

const chokidar = require('chokidar');
const EventEmitter = require('events').EventEmitter;
const fsExtra = require('fs-extra');

class Observer extends EventEmitter {
  constructor() {
    super();
  }

  watchFolder(folder) {
    try {
      console.log(
        `[${new Date().toLocaleString()}] Watching for folder changes on: ${folder}`
      );

      var watcher = chokidar.watch(folder, { persistent: true });

      watcher.on('add', async filePath => {
        if (filePath.includes('error.log')) {
          console.log(
            `[${new Date().toLocaleString()}] ${filePath} has been added.`
          );

          // Read content of new file
          var fileContent = await fsExtra.readFile(filePath);

          // emit an event when new file has been added
          this.emit('file-added', {
            message: fileContent.toString()
          });

          // remove file error.log
          await fsExtra.unlink(filePath);
          console.log(
            `[${new Date().toLocaleString()}] ${filePath} has been removed.`
          );
        }
      });
    } catch (error) {
      console.log(error);
    }
  }
}

module.exports = Observer;

These are things we do in the code above:
– import necessary module: chokidar, events, fs-extra.
– define Observer class that extends EventEmitter which can emit event (emit() method) and listen to event (on() method).
– create watcher variable using chokidar.watch() function. {persistent: true} indicates whether the process should continue to run as long as files are being watched.
watcher.on('add') is the event listener for a file added event. In the handler, we check if the added file is error.log, read content using fsExtra.readFile(), emit 'file-added' event with the content as message, delete the file using fsExtra.unlink().
– export Observer module.

Use Observer object

server.js

const Obserser = require('./services/observer');

var obserser = new Obserser();

const folder = 'Performance/logs';

obserser.on('file-added', log => {
  // print error message to console
  console.log(log.message);
});

obserser.watchFolder(folder);

What we do:
– import Observer class and initialize observer object.
– use on() method to listen 'file-added' event. In the handler, you can do anything such as: push alert message to chatwork, slack…
– call watchFolder() function.

Check result

On the project root folder, run this command:
node src/server.js

The console shows (in case there was an error.log file before):

[8/28/2019, 1:51:51 PM] Watching for folder changes on: Performance/logs
[8/28/2019, 1:51:52 PM] Performance\logs\error.log has been added.
just an error!
[8/28/2019, 1:51:52 PM] Performance\logs\error.log has been removed.

Look inside the folder, we don’t see error.log any longer.
If we create new error.log with content new error here! inside the folder. Console will immediately show:

[8/28/2019, 1:58:25 PM] Performance\logs\error.log has been added.
new error here!
[8/28/2019, 1:58:25 PM] Performance\logs\error.log has been removed.

Source Code

You can find the complete source code for this example on Github.

Conclusion

Today we’ve learned way to listen/watch a folder for changes by solving the real world problem: check log file appearance, read the content, then delete it.

In the next tutorial, we show you way to listen/watch a file for new changes:
How to watch file for changes in Node.js

Happy learning! See you again.

Further Reading

2 thoughts to “How to watch folder for changes in Node.js”

  1. This tutorial is well suited for many applications like an editor or IDE, that potentially has many open files and needs to ensure that the files are synchronized with the file system. It is also well suited for an application server that watches a directory. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *