How to auto-reload files in Node.js?

Viewed 423469

Any ideas on how I could implement an auto-reload of files in Node.js? I'm tired of restarting the server every time I change a file. Apparently Node.js' require() function does not reload files if they already have been required, so I need to do something like this:

var sys     = require('sys'), 
    http    = require('http'),
    posix   = require('posix'),
    json    = require('./json');

var script_name = '/some/path/to/app.js';
this.app = require('./app').app;

process.watchFile(script_name, function(curr, prev){
    posix.cat(script_name).addCallback(function(content){
        process.compile( content, script_name );
    });
});

http.createServer(this.app).listen( 8080 );

And in the app.js file I have:

var file = require('./file');
this.app = function(req, res) { 
    file.serveFile( req, res, 'file.js');  
}

But this also isn't working - I get an error in the process.compile() statement saying that 'require' is not defined. process.compile is evaling the app.js, but has no clue about the node.js globals.

29 Answers

node-supervisor is awesome

usage to restart on save for old Node versions (not advised):

npm install supervisor -g
supervisor app.js

usage to restart on save for Node versions that come with npx:

npm install supervisor
npx supervisor app.js

or directly call supervisor in an npm script:

"scripts": {
  "start": "supervisor app.js"
}

nodemon is a great one. I just add more parameters for debugging and watching options.

package.json

  "scripts": {
    "dev": "cross-env NODE_ENV=development nodemon --watch server --inspect ./server/server.js"
  }

The command: nodemon --watch server --inspect ./server/server.js

Whereas:

--watch server Restart the app when changing .js, .mjs, .coffee, .litcoffee, and .json files in the server folder (included subfolders).

--inspect Enable remote debug.

./server/server.js The entry point.

Then add the following config to launch.json (VS Code) and start debugging anytime.

{
    "type": "node",
    "request": "attach",
    "name": "Attach",
    "protocol": "inspector",
    "port": 9229
}

Note that it's better to install nodemon as dev dependency of project. So your team members don't need to install it or remember the command arguments, they just npm run dev and start hacking.

See more on nodemon docs: https://github.com/remy/nodemon#monitoring-multiple-directories

You can use nodemon from NPM. And if you are using Express generator then you can using this command inside your project folder:

nodemon npm start

or using Debug mode

DEBUG=yourapp:* nodemon npm start

you can also run directly

nodemon your-app-file.js

Hope this help.

There was a recent (2009) thread about this subject on the node.js mailing list. The short answer is no, it's currently not possible auto-reload required files, but several people have developed patches that add this feature.

my app structure:

NodeAPP (folder)
   |-- app (folder)
      |-- all other file is here
   |-- node_modules (folder)
   |-- package.json
   |-- server.js (my server file)

first install reload with this command:

npm install [-g] [--save-dev] reload

then change package.json:

"scripts": {
    "start": "nodemon -e css,ejs,js,json --watch app"
}

now you must use reload in your server file:

var express = require('express');
var reload = require('reload');
var app = express();

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    console.log( 'server is running on port ' + app.get('port'));
});

reload(server, app);

and for last change, end of your response send this script:

<script src="/reload/reload.js"></script>

now start your app with this code:

npm start

Here's a low tech method for use in Windows. Put this in a batch file called serve.bat:

@echo off

:serve
start /wait node.exe %*
goto :serve

Now instead of running node app.js from your cmd shell, run serve app.js.

This will open a new shell window running the server. The batch file will block (because of the /wait) until you close the shell window, at which point the original cmd shell will ask "Terminate batch job (Y/N)?" If you answer "N" then the server will be relaunched.

Each time you want to restart the server, close the server window and answer "N" in the cmd shell.

You can do it with browser-refresh. Your node app restarts automatically, your result page in browser also refreshes automatically. Downside is that you have to put js snippet on generated page. Here's the repo for the working example.

const http = require('http');
const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html; charset=UTF-8');
    res.write('Simple refresh!');
    res.write(`<script src=${process.env.BROWSER_REFRESH_URL}></script>`);
    res.end();
})

server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);

    if (process.send) {
        process.send({ event: 'online', url: `http://${hostname}:${port}/` })
    }

});

I have tried pm2 : installation is easy and easy to use too; the result is satisfying. However, we have to take care of which edition of pm2 that we want. pm 2 runtime is the free edition, whereas pm2 plus and pm2 enterprise are not free.

As for Strongloop, my installation failed or was not complete, so I couldn't use it.

If your talking about server side NodeJS hot-reloading, lets say you wish to have an Javascript file on the server which has an express route described and you want this Javascript file to hot reload rather than the server re-starting on file change then razzle can do that.

An example of this is basic-server

https://github.com/jaredpalmer/razzle/tree/master/examples/basic-server

The file https://github.com/jaredpalmer/razzle/blob/master/examples/basic-server/src/server.js will hot-reload if it is changed and saved, the server does not re-start.

This means you can program a REST server which can hot-reload using this razzle.

it's quite simple to just do this yourself without any dependency... the built in file watcher have matured enough that it dose not sucks as much as before

you don't need any complicated child process to spawn/kill & pipe std to in/out... you just need a simple web worker, that's all! A web Worker is also what i would have used in browsers too... so stick to web techniques! worker will also log to the console

import { watch } from 'node:fs/promises'
import { Worker } from 'node:worker_threads'

let worker = new Worker('./app.js')

async function reloadOnChange (dir) {
  const watcher = watch(dir, { recursive: true })
  for await (const change of watcher) {
    if (change.filename.endsWith('.js')) {
      worker.terminate()
      worker = new Worker('./app.js')
    }
  }
}

// All the folder to watch for
['./src', './lib', './test'].map(reloadOnChange)

this might not be the best solution where you use anything else other than javascript and do not depend on some build process.

const cleanCache = (moduleId) => {
    const module = require.cache[moduleId];
    if (!module) {
        return;
    }
    // 1. clean parent
    if (module.parent) {
        module.parent.children.splice(module.parent.children.indexOf(module), 1);
    }
    // 2. clean self
    require.cache[moduleId] = null;
};
Related