2

In MyModule folder, I have this two JS files.

SayHello.js

module.exports.SayHello = function() {
    return('Hello !');
}

SayByeBye.js

module.exports.SayByeBye = function() {
    return('Bye Bye!');
}

In Node.js, I want to require all files in MyModule folder and call function SayHello & SayByeBye directly something like:

require(./MyModule) 
console.log(SayHello());
console.log(SayByeBye());

EDIT:

With answer of @Yanick Rochon,I do this :

> ./app/my-module/index.js

global.SayHello = require('./my-module/SayHello').SayHello;
global.SayByeBye = require('./my-module/SayByeBye').SayByeBye;

> ./app/my-module/say-hello.js

module.exports.SayHello = function() {
    return('Hello !');
};

> ./app/my-module/say-byebye.js

module.exports.SayByeBye = function() {
    return('Bye Bye !');
};

> ./app/main.js

require('./my-module');
console.log(SayHello());
console.log(SayByeBye());

There's a section about global objects in the node documentation.

However, globals should be used with care. By adding modules to the global space I reduce testability and encapsulation. But in this case, I think using this method is acceptable.

Community
  • 1
  • 1
LeMoussel
  • 5,290
  • 12
  • 69
  • 122

2 Answers2

6

First thing first...

I believe you are mistaking Node.js with PHP or .Net, in the sense that you don't "import" into the current module what is exported in other modules. Not unless you manually do it anyway. For example, when you call

require('./my-module');

(Note that I renamed your MyModule into Node.js naming convention.)

You don't load things into the current context; you just load the script and don't assign it to anything. To access what my-module exposes, you need to assign it, or use it directly. For example :

require('./my-module').someFunction();

or

var myModule = require('./my-module');

myModule.someFunction();

Modules are not namespaces, but JavaScript objects that exposes public properties outside of their own contexts (i.e. using module.exports = ...)

Answer

You have two most popular ways to accomplish this :

Solution 1

Create an index.json file inside your folder where you want to load all of your scripts. The returned JSON object should be all the modules to load automatically :

> ./app/index.json

[
  "say-hello.js",
  "say-goodbye.js"
]

You should also consider having all your files API compatible :

> ./app/say-hello.js

module.exports = function sayHello() {
  return 'Hello !';
};

> ./app/say-goodbye.js

module.exports.sayGoodbye = function () {
  return 'Goodbye !';
};

Then load and execute everything like this :

var path = require('path');
var basePath = './app/';

var files = require(basePath);

var mods = files.forEach(function (loaded, file) {
  var mod = require(path.join(basePath, file));

  // mod is a function with a name, so use it!
  if (mod instanceof Function) {
    loaded[mod.name] = mod;
  } else {
    Object.keys(mod).forEach(function (property) {
      loaded[property] = mod.property;
    });
  }
}, {});

mods.sayHello();
mods.sayGoodbye();

Solution 2

Read all .js files inside your folder and import them. I highly recommend you use glob for this.

var glob = require("glob")
var path = require('path');
var basePath = './app/';

var mods = glob.sync(path.join(basePath, '*.js')).reduce(function (loaded, file) {
  var mod = require(file);

  // mod is a function with a name, so use it!
  if (mod instanceof Function) {
    loaded[mod.name] = mod;
  } else {
    Object.keys(mod).forEach(function (property) {
      loaded[property] = mod.property;
    });
  }

  return loaded;
}, {});

mods.sayHello();
mods.sayGoodbye();

Note on the difference between module.exports and exports

Typically module.exports === exports, but it is recommended to use module.exports for the following reason

exports = function Foo() { }         // will not do anything
module.exports = function Foo() { }  // but this will do what you expect

// however these two lines produce the same result
exports.foo = 'Bar';
module.exports.foo = 'Bar';  

For this reason, module.exports is recommended in all cases.

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
1

It's not perfect, but something like this should help you accomplish this:

var fs = require('fs');
var path = require('path');

var files = fs.readdirSync(__dirname);
var ownFilename = __filename.substr(__filename.lastIndexOf(path.delimiter) + 1);

var modules = {};
for (var i = 0; i < files.length; i++) {
        var filename = files[i];
        if (filename.substr(-3) === '.js' && filename !== ownFilename) {
                modules[filename.slice(0, -3)] = require('./' + filename);
        }
}

console.log(modules.SayByeBye());
console.log(modules.SayHello());
kpimov
  • 13,632
  • 3
  • 12
  • 18