2 - Módulos en Node.js (2 sistemas de módulos)


La primera gran diferencia en el JavaScript que se utiliza en Node.js es el concepto de módulo y como podemos utilizar la sintaxis de módulos que nació con Node.js (CommonJS) y la sintaxis moderna de JavaScript estándar llamada ECMAScript. Como se utilizan ampliamente los dos sintaxis, deberemos dominarlas y conocer sus similitudes y diferencias.

Sabemos que cuando nuestra aplicación comienza a crecer un único archivo es imposible de manejar todas las funcionalidades, lo mismo ocurre con librerías desarrolladas por otros programadores.

Un módulo contiene funciones, objetos, variables donde indicamos cuales serán exportados para ser utilizados por otros programas.

Módulo de un único archivo (sintaxis de CommonJS)

Vamos a crear un programa muy sencillo que nos permita sumar, restar y dividir números y mostrarlos por la consola. Las funcionalidades las dispondremos en un módulo de archivo y veremos como la consumimos en nuestro programa principal.

Primero creemos nuestro módulo llamado matematica.js con el siguiente código:

matematica.js
const PI = 3.14

function sumar(x1, x2) {
  return x1 + x2
}

function restar(x1, x2) {
  return x1 - x2
}

function dividir(x1, x2) {
  if (x2 == 0) {
    mostrarErrorDivision()
  }
  else {
    return x1 / x2
  }
}

function mostrarErrorDivision() {
  console.log('No se puede dividir por cero')
}

module.exports = {
  sumar,
  restar,
  dividir,
  PI
}

En este archivo podemos definir variables, funciones, objetos etc. y los que necesitamos que sean accedidos desde otro archivo los exportamos agregándolos al objeto exports:

module.exports = {
  sumar,
  restar,
  dividir,
  PI
}

Aquello que no necesitemos llamarlo desde otra archivo como en este ejemplo pasa con la función mostrarErrorDivision simplemente no la agregamos al objeto exports.

Codifiquemos ahora nuestra aplicación principal que la llamaremos ejercicio2.js y también la guardamos en la misma carpeta donde tenemos el archivo matematica.js:

const mat = require('./matematica')

console.log('La suma de 2+2=' + mat.sumar(2, 2))
console.log('La resta de 4-1=' + mat.restar(4, 1))
console.log('La división de 6/3=' + mat.dividir(6, 3))
console.log('El valor de PI=' + mat.PI)

El JavaScript que se ejecuta en un navegador web actualmente utiliza otra sintaxis propuesta en ECMAScript para hacer referencia a otro archivo (la veremos luego), en Node.js con la sintaxis de CommonJS se hace llamando a la función require e indicando el path donde se encuentra en este caso el archivo matematica.js (no es necesario indicar la extensión):

const mat=require('./matematica')

Luego la constante mat tiene acceso a todas las variables, funciones y objetos exportados.

Llamamos luego a las funciones y accedemos a las variables mediante la constante mat:

console.log('La suma de 2+2=' + mat.sumar(2, 2))
console.log('La resta de 4-1=' + mat.restar(4, 1))
console.log('La división de 6/3=' + mat.dividir(6, 3))
console.log('El valor de PI=' + mat.PI)

En nuestra consola al ejecutar nuestro programa ejercicio2.js tenemos como resultado:

modulo en nodejs

Recordemos que JavaScript nos permite desestructurar el objeto cuando llamamos a require:

const {sumar, restar, dividir, PI} = require('./matematica')

console.log('La suma de 2+2=' + sumar(2, 2))
console.log('La resta de 4-1=' + restar(4, 1))
console.log('La división de 6/3=' + dividir(6, 3))
console.log('El valor de PI=' + PI)

Tengamos en cuenta que solo podemos acceder del módulo a aquellos elementos exportados, si por ejemplo tratamos de acceder a la función mostrarErrorDivision del módulo matematica.js:

mat.mostrarErrorDivision()

Tendremos como resultado un error en tiempo de ejecución ("mostrarErrorDivision is not a function"):

modulo en nodejs con error

Esta pequeña introducción de módulos es para entender en los próximos temas cada vez que consumamos módulos que ya vienen con Node.js y de otras librerias que descarguemos de internet.

Veremos más adelante que los módulos pueden ser una carpeta que contiene un conjunto de archivos y de subcarpetas (esto es muy útil si la funcionalidad del módulo es muy compleja y por lo tanto no debería estar en un único archivo)

No nos preocuparemos por ahora de crear módulos propios más complejos ya que la forma de consumir módulos con la función require es idéntica ya sea que el módulo sea un único archivo o una carpeta.

Módulo de un único archivo (sintaxis de ECMAScript)

Por el momento presentaremos una forma fácil de utilizar la sintaxis que ya conocen de los módulos ECMAScript. Vamos a cambiar la extensión de los archivos: matematica.js por matematica.mjs (es decir js por mjs)

Luego podemos utilizar la sintaxis de ECMAScript sin problemas (en proyectos grandes veremos que podemos configurar que los archivos con extensión .js tendrán código ECMAScript)

Luego tenemos la sintaxis:

matematica.mjs
const PI = 3.14

function sumar(x1, x2) {
  return x1 + x2
}

function restar(x1, x2) {
  return x1 - x2
}

function dividir(x1, x2) {
  if (x2 == 0) {
    mostrarErrorDivision()
  }
  else {
    return x1 / x2
  }
}

function mostrarErrorDivision() {
  console.log('No se puede dividir por cero')
}

export  {
  sumar,
  restar,
  dividir,
  PI
}

Luego el archivo ejercicio2.mjs queda codificado con la sintaxis:

import {sumar, restar, dividir, PI} from './matematica.mjs'

console.log('La suma de 2+2=' + sumar(2, 2))
console.log('La resta de 4-1=' + restar(4, 1))
console.log('La división de 6/3=' + dividir(6, 3))
console.log('El valor de PI=' + PI)

modulo ECMAScript

Es decir utilizamos la sintaxis estándar de JavaScript que funciona en los navegadores.

Retornar