
Member-only story
Dependency injection container with hot-reloading in Node.js
One thing that I’ve always liked about languages like PHP is that when you modify the code, you can immediately see the results — without recompiling or restarting the application.
In JavaScript this is possible on the client side, thanks to webpack and its hot-reloading mechanism. Unfortunately, on the server side this is not so simple. If you write a server application in Node.js, you have to restart it whenever you change the code, and it can be pretty frustrating if you forget to do that and wonder why the application isn’t working as expected.
A simple solution is using a tool like nodemon, which automatically restarts the application whenever a code change is detected. It’s enough for small applications, but as they become more complex, the cost of restarting them at every code change may become significant.
I’ve been looking for a solution which makes it possible to reload only the part of the application which is affected by the code change, and keep the other modules intact. A good example is an API server, where modifying one action handler doesn’t affect the other handlers.
Reloading a module
The first step is to watch for file modifications using a tool like Chokidar. However, if you try to require()
a modified file while the application is running, you will still get the old module instead of the updated version.
The reason is that Node.js keeps an internal cache of all loaded modules, so if you require()
a file that has already been loaded, you will get exactly the same result, even if the file was modified in the meantime.
Fortunately, this cache is accessible to the application, so we can remove the cached module and force it to be reloaded:
const path = require.resolve( './my-module' );
delete require.cache[ path ];const myModule = require( './my-module' );
You can find more information about clearing the require cache here and here.
Tracking dependencies
A bigger problem is tracking and handling dependency chains. Let’s suppose that module A requires B, which in turn requires C. When C is modified, B…