Watching files for changes

We want to add a file watcher for every file requested by a client. This watcher should detect file changes and automatically push them to the client. Also, once a client disconnects, we need to clean up and remove all file watchers. To watch files for changes, we will use the asynchronous watchFile() function from the fs module:

/* server.js */
var fs = require('fs');
var app = require('express')();
var http = require('http').Server(app);
var serveStatic = require('serve-static');
var io = require('socket.io')(http);

// Serve all files from the root directory
app.use(serveStatic('.', {'index': ['index.html']}));

// Wait for socket connection
io.on('connection', function(socket){

  var watchers = [];

  // Send the content of a file to the client
  var sendFile = function(name, path) {
    // Read the file
    fs.readFile(path, 'utf8', function (err, data) {
      // Emit the content of the file
      io.emit(name, data);
    });
  };

  // Wait for events on socket
  socket.on('watch', function(obj){

    if (!watchers.hasOwnProperty(obj.name)){

       console.log("Watching " + obj.name);
       watchers[obj.name] = obj;
       sendFile(obj.name, obj.path);

       // Watch the file for changes
       fs.watchFile(obj.path, function (curr, prev) {

        sendFile(obj.name, obj.path);
      });
    }
  });

  socket.on('disconnect', function(){
    watchers.forEach(function(obj) {
      fs.unwatchFile(obj.path);
    });
  });
});

http.listen(3000, function(){
  console.log('listening on 0.0.0.0:3000');
});

In the preceding code, we add a watchers array that contains all the current file watchers. This makes it easy to clean up and unwatch all the files in the disconnect handler via unwatchFile() once the connection is closed. In the connection handler, we add the watchFile() function. This function pushes the content of a file to the clients once it’s changed.

These few lines are all the magic that we need to monitor files and push them to the client when they are updated, pretty cool! Also, keep in mind that we completely neglected proper error handling in this simple example.

Finally, we run the server via the node server.js command and open http://localhost:3000/ for the client application.