Caching of Modules in NodeJS

Sharing is Caring

In this post, I am talking about caching of Modules in NodeJS.

We have the following files

//greet.js
module.exports = {
    greeting: "Hello!",
    greet: function(){
        console.log(this.greeting);
    }
}

//app.js
var greet1 = require("./module/greet");
greet1.greet();
greet1.greeting = "Yooo!";
greet1.greet();



var greet2 =  require("./module/greet");
greet2.greet();

On executing node app.js, on first glance, we’d expect the output to be:

Heyyyyyy?
Yooo!
Heyyyyyy?

Our logic is that greet2.greet() would print “Heyyyyyy?” because it’ll get a fresh copy of module.export from greet.js file.

But on the contrary, the output of the above program is:

Heyyyyyy? 
Yooo! 
Yooo! 

So what actually happens is that – when greet1 function calls require("./module/greet")function, a new module for greet.jsis created and compiled. After compilation and before returning node stores the cached copy of module.exports in the variable cachedModule.exports, and then returns module.exports

 

Since objects in Javascript are passed by reference, cachedModule.exportspoints towards the same location in memory where greet1 points at. Now when we made a change to greet1 by mutating the greeting property, cachedModule.exports too changes because ultimately both cachedModule.exportsand greet1 are the same. They point to the same object.

So now when greet2 calls the require("./module/greet")function, instead of recompiling greet.js, node checks if there’s a cached copy of module.exports.If found, it returns it and hence saves time which would’ve got lost in recompiling greet.js.

So greet2 essentially gets the same object which is pointed towards by greet1. This is the reason greet2.greeting()prints “Yooo!”.

 

Node also provides a feature to delete the stored cache. It’s done by executing the following statement:

delete require.cache[require.resolve(module)]

So if one wants to always reload the module, he can add this function:

function requireUncached(module){
    delete require.cache[require.resolve(module)]
    return require(module)
}

 

Takeaways from this lesson:

Whenever a module is required, node checks if there exists cached copy of its module.exports. If exists it returns the cached copy, otherwise it compiles that module and makes cached copy of its module.exports and then returns module.exports.

 

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *