Saturday, November 3, 2012

Module Caching in Node.js

There was an interesting question on stackoverflow about whether singletons can be implemented in Node.js  via modules: Singleton pattern in nodejs - is it needed?

Ignoring any discussion about the singleton as anti-patterns, the question comes down to how Node.js caches modules.

The Node.js docs for Module Caching & Module Caching Caveats state:
Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file. Multiple calls to require('foo') may not cause the module code to be executed multiple times. 
Modules are cached based on their resolved filename. Since modules may resolve to a different filename based on the location of the calling module (loading from node_modules folders), it is not a guarantee that require('foo') will always return the exact same object, if it would resolve to different files. 
"may not" and "not a guarantee" bother me -- under what circumstances will require('foo') not return the same object?

Turns out to be pretty simple: If the foo in require('foo') resolves to the same file in the filesystem (excluding hardlinked files), the same object is returned. If foo resolves to different files, in different directories, then each would be loaded/executed/cached individually.

Under the hood, fs.realpath is used to resolve the canonicalized absolute pathname to the file -- this means that symlinks to a file all resolve to the same file.