RSS Feed

Módulos en NodeJS

4

febrero 11, 2012 by - @pjnovas

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


  • Anónimo

    Muy bueno, en especial nunca había pensado en las reglas que había para setear propiedades en el exports. Lo del setTimeout puede sonar medio raro pero estoy seguró que mucha gente trató de hacerlo jaja.
    Está bueno también saber que cuando vas a usar solo una parte de un módulo cuando lo estás importando, podes hacer cosas como:

    var isArray = require('util').isArray;
    // [...]
    isArray(new Array) === true

    • Pjnovas

      Sep, voy a armar otro para mostrar como usar una clase prototypada, el new y como exponer y que exponer de esa clase ;)

  • Pingback: RequireJS: Módulos y Dependencias | fernetjs

  • Pingback: maillot de foot pas cher