i'm with substack here. my arguments on this are:
the HOW instances are created and IF it's a singleton or not are, in fact, implementation details and should be hidden most of the time from the user.
when i var foo = require('something') , then it's not obvious, that this is a constructor. a factory function is in 99% of the time clear.
factory functions help to abstract away the details, so it is easier to exchange the hidden parts. This argument is not that important in js as it is in static typed langs, but still valid.
on the other side i also think Rick and Mikeal are right regarding style and amount of code to maintain. a thing like that:
module.exports = function createLogger(){ return require('customLogger').createLogger()}
is awful. a factory function should definitely do something more than just return it's product.
and about static init, what i did about it in a lib: the main entrypoint of the whole package was a function which took configuration and returned a factory function. the user required the package once and re-exported the returned factory function. usage:
reexport.js:
module.exports = require('thelib')({/*annoying options*/})
myLogic.js:
var someWorkingFunc = require('./reexport')()
the user may one or more independently configured factories of the lib and use them in different ways. (and can wrap it's own favorite api-style around mine for internal code.)
PS: this is also one way to do simple DI:
module.exports = function entry(preferredChannel){
preferredChannel = preferredChannel || fs.createWriteStream('/var/log/myapp')
return function getLogger(loggerLevel){return new AwesomeLogger(preferredChannel, loggerLevel)}