# Node.js: using fs.watch to re-import CommonJS modules.

> *Disclaimer. This is an investigation into what is possible. Not a fully-blown solution into how to reload modules without restarting the whole server.*

In a [previous article](https://gemmablack.dev/nodejs-refreshing-a-module-using-requirecache), I was investigating how to use `require.cache` to refresh a module by deleting it and requiring it again. eg.

```javascript
require('./some-module')

// use module

delete require.cache[require.resolve('./some-module')]

// use reloaded module
```

However, on its own, I can’t really think of a good use case to delete a cached module like that. My aim was to attempt to reload a module without restarting the server – mainly to reduce the wait time. And it works! To a degree.

## fs.watchFile

So I have a `child.js` module that doesn’t export anything.

```javascript
// child.js
console.log('hi', Date.now())
```

I then have a `main.js` that imports the `child.js`.

```javascript
const fs = require('fs')
require('./child')

fs.watchFile(require.resolve('./child.js'), () => {
    console.log('refresh')
    delete require.cache[require.resolve('./child')]
    require('./child')
})
```

Running `node main.js` with `fs.watchFile` kept the server running on its own. So every time I made a change to the file, it would refresh the child module as I changed the logged output.

The only downside is that I noticed a little bit of lag when using `fs.watchFile`. It didn’t pick up all the changes. So I tried `fs.watch`.

## Using fs.watch instead of fs.watchFile

The `child.js` file was the same. The `main.js` was the same with everything except `fs.watchFile` was replaced with `fs.watch`.

And the lag was gone. Changes were reflected instantaneously.

Now the reason for this is because `fs.watchFile` uses polling. And the Node docs recommend using `fs.watch` instead.

> Using [`fs.watch`](http://fs.watch)[`()` is more e](https://nodejs.org/docs/latest/api/fs.html#fswatchfilename-options-listener)fficient than `fs.watchFile` and `fs.unwatchFile`. [`fs.watch`](http://fs.watch) should be used instead of `fs.watchFile` and `fs.unwatchFile` when possible. - [https://nodejs.org/docs/latest/api/fs.html#fswatchfilefilename-options-listener](https://nodejs.org/docs/latest/api/fs.html#fswatchfilefilename-options-listener)
> 
> ##### **Caveats**
> 
> The [`fs.watch`](http://fs.watch) API is not 100% consistent across platforms, and is unavailable in some situations.

## An ExpressJS server

So now, how could I potentially get module reloading when a file changes without restarting the entire server?

First. Here’s a very basic Express.js server.

```javascript
// -- child.js
module.exports = (req, res) => {
    res.send('Hello, World!');
}

// -- main.js
const express = require('express');
const handle = require('./child');

const app = express();

app.get('/', handle);

const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
```

Now, when I run the server doing `node main.js`, and make a request to the root path, `http :3000` (using HTTPIE), I get my **“Hello, World!”** response.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731867180899/5cc4249e-1ac2-4823-a9b1-7225d0ff3a6f.png align="center")

But without Nodemon or some other way of watching the file, changes to the file won’t be reflected. So let’s change that.

1. The `main.js` file has to be adjusted so that the `child.js` module is lazily-loaded when the root path is requested.
    
2. A file watcher was added to watch changes to the `child.js`.
    

```javascript
const express = require('express');
const fs = require('fs');

fs.watch(require.resolve('./child.js'), () => {
    delete require.cache[require.resolve('./child')]
    require('./child')
})

const app = express();

app.get('/', (...args) => {
    require('./child')(...args)
});

const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
```

And voila 🎉!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731869307507/0435dbcb-9695-4c3f-a91a-909dbbd17a2b.png align="center")

I made a change to the file, it was reloaded without restarting the server!

And for development, this is fine. We can use a variable to have reloading in a development only environment running it like `MODULE_RELOAD=true node main.js` .

```javascript
const express = require('express');
const fs = require('fs');
const handle = require('./child');

const app = express();

if (process.env.MODULE_RELOAD) {
    fs.watch(require.resolve('./child.js'), () => {
        console.log('Server reloaded')
        delete require.cache[require.resolve('./child.js')]
        require('./child')
    })
    
    app.get('/', (...args) => {
        require('./child')(...args)
    });
} else {
    app.get('/', handle);
}

const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
```

Of course, loading one file route path isn’t all that helpful either. But, I did say this was an investigation 😉.
