I was working on a singleton pattern object to manage some global configuration in Oystr today and came across a potentially dangerous realisation that I tested and turned out to be true. The issue I found is that if you are using a module that exports a singleton, that singleton will only be the same object across modules that are using THE SAME VERSION of the that module. This is a pretty important “gotcha” and could create a huge debugging headache if not managed correctly. To demonstrate this exact problem, I’ve created a project hosted on my GitHub at https://github.com/chris-tomich/mymemorysucks/tree/master/NodeVersioningAndSingletons and have provided a guide below of this exact issue.
What the Sample Application Does
The sample application in NodeVersioningAndSingletons does something pretty basic. It sets the name on the singleton-based greeting module (known as mymemorysucks-greeting-module), and asks the friend module (known as mymemorysucks-friend-module) to introduce themselves. The friend module in turn uses the greeting module to create an appropriate greeting and then the app display their greeting to the console.
To demonstrate the issue, I’ve created two versions of this simple application. One version shows the output when the main application and the friend module are both using the same version of the greetings module. This version is called app-same-version. The other version shows the output when the main application and the friend module are both using different versions of the greetings module. This version of the application is called app-diff-version.
Output of the app-same-version
The output of the app-same-version application is as you would expect. The main app.js script sets the name to “Chris” and then the friend object greets Chris as illustrated with the screenshot below.
Output of the app-diff-version
This is the problematic version. In this version, the main app has been set to use a different version of the greetings module to the friend module. When you run the application you get the following output.
As you can see, it now greets “undefined” as a different version was set.
Why does this happen and how to I fix it?
If you take compare the node_modules directories from both of the applications, they differ in that the mymemorysucks-friend-module will import it’s own version of the greeting module separate to the app-diff-version application. In the app-same-version application, the mymemorysucks-friend-module doesn’t do this.
At this point in time, I have no ideas on how to fix this situation if say it’s occurring with two external modules that you’ve imported into your project. The only ideas I have around fixing this is in managing the package versions and to carefully define specific versions of modules that export “singleton” objects. In other words, in your package.json file “dependencies” list, to specify a specific version for all your modules to use. If you have any better ideas beyond this it would be great if you could share them and I’ll add them to this post.