En nodejs cuando queremos usar un módulo, paquete o script creado por nosotros debemos importarlo y para eso seguimos la convención commonJs
CJS o si tenemos la ultima version podemos usar emacscript module
ESM.
Modules - require
En nodejs cuando queremos usar un módulo, paquete o script creado por nosotros debemos importarlo y para eso seguimos la convención commonJs
CJS o si tenemos la ultima version podemos usar emacscript module
ESM que aun esta en modo experimental.
// CJS
const requiredjs = require("module");
// ESM
import { requirejs } from 'module'; // or import 'module'
Import
El path es la ruta en donde se va a buscar nuestro modulo, existen básicamente dos formas de llamar nuestros módulos: la primera es llamar un módulo del core o un paquete externo que usualmente instalamos con npm y se guarda en la carpeta node_modules, la segunda es llamar un script creado por nosotros mediante su path.
- Si es un módulo core se busca en la carpeta lib y si es un paquete externo lo va a buscar en una de las jerarquías de la carpeta node_modules, esto lo podemos observar en los paths de nuestro module, los scripts se van a buscar en ese orden.
const http = require('http') // sin path
# Podemos tener un node_module para nuestro archivo,
# para nuestro proyecto, para nuestro usuario en el sistema o uno global.
# ejecutemos este comando en la ubicación de nuestro archivo y
# lo comparamos llamandolo fuera de nuestro proyecto.
> node -p "module"
- Si es un script debemos llamarlo mediante su path el cual puede ser absoluto o relativo.
// absolute path
const myscript = require('/home/user/project/script.js')
// relative path - script se encuentra en la misma carpeta en el mismo nivel
const myscript = require('./script.js')
Export
Antes de importar un script para usarlo en nuestro archivo este se debe haber exportado, para poder llamarlo y usarlo desde otro archivo.
// square.js
class Square {
constructor(width) {
this.width = width;
}
area() {
return this.width ** 2;
}
};
// se modifica todo el export para que sea la clase
// solo se puede hacer mediante module
module.exports = Square;
// circle.js
const { PI } = Math;
// agrego funciones al export, como un objeto
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;
Wrapper
Cuando se llama un archivo, internamente nodejs lo manipula para agregarle algunas funciones y metadata, es por esto que podemos obtener información importante, como el require, module, __filename, etc.
// wrapper.js
// import a file
require('./circle')
// export a function
exports.myFunc= (r) => PI * r ** 2;
console.log("Wrapper: ", require('module').wrapper)
console.log("Exports: ", exports)
console.log("Require: ", require)
console.log("Module: ", module)
console.log("Filename: ", __filename)
console.log("Dirname: ", __dirname)
Require
Como lo vimos anteriormente tenemos a module
que es la referencia al módulo que estamos corriendo y con require
podemos identificar quien ha llamado el módulo y algunas otras propiedades que nos pueden ser útiles para que nuestro script se comporte de una manera si es requerido y de otra si es usado independiente.
// square.js
class Square {
constructor(width) {
this.width = width;
}
area() {
return this.width ** 2;
}
};
if (require.main === module) {
// Estoy corriendo el script - fue llamado 'node square.js param' desde consola
if (isNaN(process.argv[2])) throw new Error("missed or wrong parameter")
const square = new Square(process.argv[2]);
console.log(`The area of mySquare is ${square.area()}`);
} else {
//Fue requerido por otro archivo
module.exports = Square;
}
Cache
Cuando cargamos por primera vez un módulo o un archivo este queda guardado gracias al mecanismo de cache de Nodejs, esto significa que la siguiente vez que sea llamado este archivo lo va tomar de la cache, a menos que usemos new en el caso de una clase o que el archivo se pueda resolver con otro path, un ejemplo puede ser llamar un módulo en primera instancia con mayúsculas y después en minúsculas, esto node lo interpreta como algo diferente.
// squareCache.js
class Square {
constructor(width) {
this.width = width;
console.log("Square called");
}
area() {
return this.width ** 2;
}
};
module.exports = new Square('4');
// index.js
const square = require('./squareCache') // 1 call and cached
const square2 = require('./SquareCache') // 2 call because of S in name and cached
const square3 = require('./SquareCache') // none call already cached
console.log(square.area());
console.log(square2.area());
console.log(square3.area());