Loading

Quipoin Menu

Learn • Practice • Grow

node-js / Watching Files
tutorial

Watching Files

Imagine you're a security guard watching a door. You don't stand there constantly checking if it's opening – you just wait for the door to move and then react. In Node.js, you can watch files and directories for changes, and react when something happens.

Watching Files in Node.js

Node.js provides two main methods to watch for file system changes:
  • fs.watch() – Efficient, cross-platform, but less detailed
  • fs.watchFile() – More detailed, but less efficient (polling-based)

Think of `fs.watch()` as a motion sensor – it tells you something moved. `fs.watchFile()` is like checking a security camera every second – more detail but uses more resources.

1. Using fs.watch() (Recommended)

`fs.watch()` watches a file or directory for changes. It's efficient because it uses the operating system's native file change notification system.
const fs = require('fs');

<!-- Watch a single file -->
fs.watch('config.json', (eventType, filename) => {
  console.log(`Event type: ${eventType}`);
  if (filename) {
    console.log(`Filename: ${filename}`);
  }
 
  <!-- React to the change (e.g., reload configuration) -->
  console.log('Config file changed! Reloading...');
});

Watching a Directory
<!-- Watch a directory for any changes -->
fs.watch('./uploads', { recursive: true }, (eventType, filename) => {
  console.log(`${filename} - ${eventType}`);
 
  if (eventType === 'rename') {
    <!-- File added or deleted -->
    console.log('File was added or removed');
  } else if (eventType === 'change') {
    <!-- File content changed -->
    console.log('File content was modified');
  }
});

2. Using fs.watchFile() (Polling-based)

`fs.watchFile()` polls the file at regular intervals to check for changes. It gives you more detailed information but uses more CPU.
<!-- Watch a file with polling (check every 2 seconds) -->
fs.watchFile('data.log', { interval: 2000 }, (curr, prev) => {
  console.log('File changed!');
  console.log('Previous size:', prev.size);
  console.log('Current size:', curr.size);
  console.log('Previous modified:', prev.mtime);
  console.log('Current modified:', curr.mtime);
});

Stopping the Watch

When you no longer need to watch, you should close the watcher to free resources.
const watcher = fs.watch('file.txt', (eventType, filename) => {
  console.log('File changed');
});

<!-- After 10 seconds, stop watching -->
setTimeout(() => {
  watcher.close();
  console.log('Stopped watching');
}, 10000);

<!-- For watchFile, use unwatchFile -->
fs.unwatchFile('data.log');

Practical Example: Auto-reload Configuration

This is a common pattern – watch a config file and reload when it changes.
const fs = require('fs');

let config = {};

function loadConfig() {
  try {
    const data = fs.readFileSync('config.json', 'utf8');
    config = JSON.parse(data);
    console.log('Configuration loaded');
  } catch (err) {
    console.error('Error loading config:', err);
  }
}

<!-- Load initial config -->
loadConfig();

<!-- Watch for changes -->
fs.watch('config.json', (eventType) => {
  if (eventType === 'change') {
    console.log('Config changed, reloading...');
    loadConfig();
  }
});

console.log('Watching config.json for changes...');

Practical Example: Log File Monitor
const fs = require('fs');
const path = require('path');

const logFile = 'app.log';
let fileSize = 0;

<!-- Get initial file size -->
try {
  const stats = fs.statSync(logFile);
  fileSize = stats.size;
} catch (err) {
  console.log('Log file does not exist yet');
}

<!-- Watch for changes -->
fs.watch(logFile, (eventType) => {
  if (eventType === 'change') {
    const stats = fs.statSync(logFile);
    const newSize = stats.size;
   
    if (newSize > fileSize) {
      const addedBytes = newSize - fileSize;
      console.log(`${addedBytes} new bytes written to log file`);
     
      <!-- Read only the new data -->
      const buffer = Buffer.alloc(addedBytes);
      const fd = fs.openSync(logFile, 'r');
      fs.readSync(fd, buffer, 0, addedBytes, fileSize);
      fs.closeSync(fd);
     
      console.log('New log entries:');
      console.log(buffer.toString('utf8'));
    }
   
    fileSize = newSize;
  }
});

console.log('Monitoring log file...');

Platform Differences

Platformfs.watch Behavior
WindowsEvent types may be 'rename' or 'change'. Filename may not always be provided.
macOSUses kqueue – reliable but may have limitations with many watchers.
LinuxUses inotify – very reliable, supports recursive watching.

Two Minute Drill

  • Use `fs.watch()` for efficient, event-driven file watching.
  • Use `fs.watchFile()` when you need detailed change information (size, timestamps).
  • Always close watchers when done to prevent memory leaks.
  • `fs.watch()` may not provide filename on all platforms – handle accordingly.
  • Great for auto-reload, log monitoring, build tools, and live updates.

Need more clarification?

Drop us an email at career@quipoinfotech.com