Module Caching in Node

In Node.js we use the CommonJS module pattern for sharing code between files. In this article, I'll explain how to use the require keyword and how it's related to module caching in Node.

CommonJS

CommonJS is the pattern used in Node.js to share functionality from on file to others. A typical Node module might look something like this.

// maths-helpers.js

exports.add = (x, y) => x + y;

exports.subtract = (x, y) => x - y;

To use the code defined in maths-helpers.js we would use the require keyword.

const helpers = require('./maths-helpers.js');

const total = helpers.add(5, 10);

console.log(total); // 15

Simple enough, right?

Module Caching in Node.js

Let's look at another example which isn't as simple.

// counter.js

let count = 0;

exports.increment = () => {
  count ++;
}

exports.total = () => {
  return count;
}

Here we have another simple module that counts the number of times the increment method has been called. Let's use it.

const counter1 = require('./counter.js');
const counter2 = require('./counter.js');

const counter1.imcrement();
const counter1.increment();

console.log(counter1.total()); // 2
console.log(counter2.total()); // 2

Pretty weird right? We create two counters and increment counter1 twice. This gives it a total of 2. When we check the value of counter2 it's also 2! So what's happening here?

In Node.js, the first time you require a module it gets cached. Each subsequent time the module is required you are actually accessing the cached instance.

Exceptions

There are a few exceptions to this caching rule. The first exception is if import path used for each module is different. This may seem obvious, but it can catch you out if you are using a case-insensitive operating system (MacOS or Windows).

The second main exception can only occur when using npm version 2 or below. Let's say your project requires moduleA and moduleB from your node packages. If moduleA and moduleB both require moduleC they will both end up with different instances of moduleC. This is due to the way older versions of npm work. Each module would get its own copy of its dependencies. In more recent versions, dependencies are flattened.

Conclusion

Now you know a little more about how require works in Node.js. There are a few quirks that you need to be aware of but they are simple enough to understand. Module caching can be very useful if used correctly, and now you know more about it, you can use it to your advantage. Go build something cool!

Join my newsletter to receive blog posts 2 weeks early