11

I would like to know how to reload a Node.js module at runtime.

Let's say I have the following code:

index.js

var myModule = require("./app.js");

app.js

var express = require("express");
express.listen(3000, function() {
    console.log("app listening on port 3000");
});

I tried multiple ways to reload my module required in the index.js module. But the Express app won't restart.

I would like to keep the index.js running, because it handles recompiling Babel modules on the fly. And the app.js module with the express server needs to be completely restarted.

Is there any way to do this without starting a second process for the app.js?

Aurora0001
  • 13,139
  • 5
  • 50
  • 53
Playdome.io
  • 3,137
  • 2
  • 17
  • 34

4 Answers4

11

require-uncached is an npm module that will clear the cache and load a module from source fresh each time, which is exactly what you seem to be interested in according to your title. To use this, you can simply use the following code:

const requireUncached = require('require-uncached');
requireUncached('./app.js');

Before doing this, it's probably necessary to ensure that all of the previous app.js's code (including the Express server) is stopped so that they don't conflict for the same port.

Also, I would suggest considering whether this approach is really the best answer - I'm sure a library such as pm2 could handle stopping and restarting a Node instance without the risk of unwanted data hanging around, which might cause a memory leak.

Aurora0001
  • 13,139
  • 5
  • 50
  • 53
  • I am using browserify to compile my client code also when i write the server code in babel i would like to have it reloaded too. And my goal with this is to avoid having multiple nodejs windows why developing, One for the client code bundler and one for the express server. I look into this and check your answer as soon as i can. Thank you! – Playdome.io Dec 05 '16 at 17:36
  • 1
    @Azarus I can understand why you don't want to run two Node instances at once (I wouldn't want to if I could help it!), I'm just a bit wary that this approach might break. Still, give it a try and let me know how it goes - I'll try to give you help with any issues that you get while following my answer. – Aurora0001 Dec 05 '16 at 17:38
4

It's simple now, I prefer write it myself for less dependencies .


function clearModule(moduleName) {
  let mp = require.resolve(moduleName)
  if (require.cache[mp]) {
    delete require.cache[mp]
    console.log(`[clear] module: ${mp}`)
  }
}

function requireReload(moduleName) {
  clearModule(moduleName);
  return require(moduleName);
}

NicoNing
  • 3,076
  • 12
  • 23
3

If all you're looking to do is restart the server without restarting the process I would recommend using the http.Server.close method. According to the express docs the app.listen method returns an http.Server object, so a reload would look something like this:

app.js

const express = require("express");

app = express();

// Define the listener function separately so it can be used on restart
function listener() {
  console.log("app listening on port 3000");
}

// start the server and save a reference to it for our restart function
const server = app.listen(3000, listener);

// Export a restart function to be used by index.js
exports.restart = function() {
  server.close(function() {
    // Server is closed, start listening again
    server.listen(3000, listener) // Use the same listener function as app.listen
  });
};

index.js

const myModule = require("./app.js"); // Output: "app listening on port 3000"

// Restart the server, keep the process
myModule.restart(); // Output: "app listening on port 3000"
youngwerth
  • 602
  • 5
  • 11
0

I would suggest you to use lazyload in web pack where I have my own post in this link.

First App

angular.module('myApp', ['ui.router','oc.lazyLoad'])
    .config(function ($stateProvider, $locationProvider, $ocLazyLoadProvider) {
            $stateProvider
                .state("home", {
                    url: "/home",
                    templateUrl: "Home.html",
                    controller: 'homeCtrl',
                    resolve: { 
                        loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
                            return $ocLazyLoad.load('homeCtrl.js');
                        }]
                    }
                })
            .state("profile", {
                url:"/profile",
                templateUrl: "profile.html",
                 resolve: {
                      loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
                      return $ocLazyLoad.load('someModule.js');
                        }]
                    }
            })

    });

Second App

(function () {
var mynewapp=angular.module('someApp',['myApp']);

mynewapp.config(function(){

  //your code to route from here! 

});
      mynewapp.controller("profileCtrl", function ($scope) {

            console.log("reached profile controller");
        });

})();

also a live Plunker

Community
  • 1
  • 1
Aravind
  • 40,391
  • 16
  • 91
  • 110
  • Is this an Angular-only solution? If so, I don't think that's going to be particularly useful, since the OP wants to restart a server-side ExpressJS server. – Aurora0001 Dec 05 '16 at 18:02
  • 1
    My question has nothing to do with angular, its a nodejs question. – Playdome.io Dec 05 '16 at 19:55