I have a question about sharing dependencies between node modules. I had almost 100 different stackoverflow-questions opened, read about di in node, singleton and nothing really seemed quite right.
As I'm new to node, I created an express app (api) to play around with. With more features the file grew fairly quickly in size, so I decided to split routes up with the express use method
const express = require('express');
const app = express();
...
app.use('/', require('./routes/index');
...
At first that looked like a nice approach. But at the moment my logging stopped working it became, what seems to be a "unsolvable" problem.
Before I split up the routes, i instantiated my logger (winston) inside my app file and used it inside my routes:
const winston = require('winston');
...
const logger = winston.createLogger({...});
...
app.get('/some-route', (req, res) => {
logger.info('Accessed some-route');
...
});
Since my routes are now separated, this approach does not work anymore.
After googling (a lot), I came across some solutions:
- Depend on nodes module caching:
I created a module that instantiates my logger end exports it. Now every time I require the logger file it should theoretically using the same instance, since node caches the module. This works quite fine, but seems absolutely wrong. Should you really depend on a cache? Since the caching is case-sensitive too, I can't expect everyone to correctly use it.
- Globals
In the past I started learning PHP as my first programming language. Even back then the concept of using global variables weren't advised. When first using javascript in the browser, encapsulating "modules" with anonymous functions were also preferred to not pollute the global namespace and create capsuled features. I don't think using globals is the way to go.
- Using handlers
Using special handlers to pass dependencies up. But this is tedious and produces a large overhead.
index-handler.js
module.export.getIndex = function(logger) {
return function(req, res, next) {
logger.info('Do some logging');
...
}
}
app.js
...
-- instanciate the logger as above
const logger = ...
...
const indexHandler = require('handlers/index');
app.use('/', indexHandler(logger));
- Dependency Injection Containers Libraries
After all I read, every module in node should only depend on itself. Many posts said that using singletons or di isn't necessary, in fact it would be wrong the way node works.
There were a few more approaches, but those are the most common when searching.
I may want to give another example to clarify my problem: My app uses a configuration file (settings.json). I normally required it like this:
let config;
try {
config = require("./settings.json");
} catch (err) {
console.error(
`Application could not start. Ensure you created a settings file`
);
process.exit(1);
}
Since the config variable was available, every route could use it. After splitting up, this does not work anymore. Even if I could require the config file in every module, I don't think it should be done this way. Or am I wrong?
This question really bugs me. Finding no clear solution is frustrating. I hope someone can give me a push in the right directionor at least provide me with some more information that I can use.
Thanks in advance