Módulos en NodeJS
NodeJS tiene un sistema de módulos bastante simple: cada archivo .js es un modulo (archivo de servidor, no confundir con contenido estático), veamos 2 módulos que se encuentran en el directorio root y son utilizados desde nuestro server app.js:
app.js //servidor NodeJS
foo.js //un módulo
bar.js //otro módulo
var http = require('http'); // módulo Core de Node
var foo = require('./foo.js');
var bar = require('./bar');
En nuestro app.js referenciamos a ambos módulos foo y bar, con ‘./’ es el path relativo al que lo esta llamando, en este caso app.js.
Si utilizamos ‘/’ vamos a estar indicando el path absoluto al archivo y si no usamos ‘/’ ni ‘./’ es un módulo Core o está en la carpeta node_modules.
Se puede escribir o no la extension, ya que Node primero comprueba que exista el nombre exacto, despues prueba con extension .js, después .json y luego .node. Por lo que de una va a encontrar el bar.js.
Los archivos .js son interpretados como archivos de texto javascript, los archivos .json son parseados como archivos de texto JSON y .node son interpretados como modulos addons compilados con dlopen
En cada módulo tenemos como objeto global el module y dentro de este, un objeto exports con el cual vamos a publicar los accesos a nuestro módulo desde otros.
//podemos evitar el module, ya que es nuestro global
exports.enviarMensaje = function(mensaje) {
console.log('Mensaje recibido en módulo foo: ' + mensaje);
};
var foo = require('./foo.js');
foo.enviarMensaje('hola módulo foo!');
//imprime: Mensaje recibido en módulo foo: hola módulo foo!
La asignacion al exports tiene que ser inmediata, no podemos hacerla en callbacks, por ejemplo esto no funciona:
setTimeout(function() {
module.exports.algo = true;
}, 100)
Si declaramos una variable dentro de un módulo, esta va a ser privada al módulo, recuerden que si no la asignamos al objeto exports no va a ser accesible desde otro módulo:
var nombre = 'Pepe';
exports.getNombre = function (){
return nombre;
};
Si no ponemos el var que pasa?, bueno estamos asignando al objeto global, pero el global del módulo, por lo que es lo mismo que lo pongamos o no, de todas formas, siempre es mejor poner el var porque nos puede pasar lo siguiente:
exports.algo = function (){
foo = 'Pepe';
var baz = 'Pepe2';
};
En ese caso foo va a ser global para todo el módulo, y puede que no sea algo que esperamos:
var foo;
exports.algo = function (){
foo = 'Pepe';
var baz = 'Pepe2';
};
De esa forma queda claro que usamos la global foo en la funcion y creamos una baz a nivel de la función.
Pueden ver mas sobre el comportamiento del var en Alcance de Variables (var scope) y Variables Globales