0

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?

BrDaHa
  • 5,138
  • 5
  • 32
  • 47

2 Answers2

1

Yes, you should be requireing your ./log file because you are creating a new instance of Winston. Your log file should export the Winston logger instance you created in it with something like:

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
    })
    ]
});
module.exports = logger

Then in your other code you can:

const logger = require('./log')

and get the same instance.

Mark
  • 90,562
  • 7
  • 108
  • 148
  • Did something change in module caching in node 8x? – BrDaHa Oct 12 '17 at 22:32
  • No modules are still cached. When you create a `new` instance you aren't changing the default instance, you are making a new one. So you need to export that. If you just import Winston, you'll get the default not the one you created and configured. – Mark Oct 12 '17 at 22:34
1

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 :)

radar155
  • 1,796
  • 2
  • 11
  • 28