Search code examples
javascriptnode.jsrequirewinston

Calling require does not return the same object


I know how module loading is supposed to work in node.js, but I'm not observing the correct behavior (and it actually seems there is a slight discrepancy if you look in the comments on this answer)

Using nodejs 8.2.1, I have the following structure:

app
 |
 + server.js
 + log
 |  |
 |  + index.js
 + db
    |
    + index.js

In server.js, I call require('./log'), and in /log/index.js, I require('winston') and configure it like so:

let logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)({
      name: 'console',
      level: logLevel,
      handleExceptions: true,
      json: false,
      colorize: process.env.NODE_ENV === 'dev',
      timestamp: true
    })
  ]
});

According to this answer, I should be able to just require('winston') from any other module, and I would get that same configured instance. What I'm actually seeing is, when I require('winston') in db/index.js, a default winston instance is in memory, with no configuration at all. I've stepped through the require.cache as well; no other modules are added to the cache, so as far as I can tell, the same configured instance should be returned, if the cache is working properly. I've verified that the code in log/index.js is being called before the module in db/index.js is being loaded as well.

Any ideas? Should I just be requireing my ./log module in all my dependent modules?


Solution

  • Any ideas? Should I just be requireing my ./log module in all my dependent modules?

    Yes you should. Like you said, when you require a module already required by a parent module, you are accessing to the same object. But actually with winston you are importing a constructor (in fact, to configure it, you define a variable called logger and you create a NEW winson logger).

    You should only export logger from logs/index.js (and use const instead of let)

     const logger = new (winston.Logger)({ ... })
     module.exports = logger
    

    in another module you could do

    const logger = require('./log/index.js') // './log' is the same
    

    logger will always be the same object :)