Después de mostraros cómo crear un servidor básico con Node.js, que fuera capaz de escuchar en un puerto concreto, aunque siempre contestara igual, nuestro conocido «Hola Mundo», seguimos avanzando en el aprendizaje de la programación de Javascript en el servidor.
Nuestro siguiente proyecto, es añadir a ese servidor la capacidad de servid paginas estáticas y rutear peticiones, a la vez que empezamos a poner un poco de orden en nuestro código.
Nuestro punto de partida:
Fijaros que encerramos todo nuestro código en una función (línea 6), incorporamos un módulo de node.js (linea 4), y terminamos llamando a nuestra función (linea 17)
Los módulos
Lo primero que nos vamos a plantear es ver como podemos partir nuestro código en diferentes ficheros; el motivo ya lo sabéis: mejorar la legibilidad de nuestro trabajo y sus posibilidades de reutilización.
Si observamos la linea 4, vemos que la funcionalidad de inclusión de código ya esta resuelta en Node.js; la función «require» accede a un archivo externo y lo lee, dejando en la variable dicho archivo .
Nosotros solo tenemos que aprender como crear esos módulos, y a continuación veréis lo fácil que es hacerlo; solo tenemos que modificar nuestra ultima linea asi:
En la línea 17 hemos declarado que queríamos exportar la función «inicio» como resultado de este fichero; tras esto podemos crear un nuevo módulo, al que llamaré «start.js» con este código:
En la línea 4 le indicamos que importe el fichero «server.js», y en la 6, podemos utilizarlo como función.
Habrá casos en donde nos interesará exportar mas de un objeto, y también lo podemos hacer, así como cambiar el nombre para la exportación; por ejemplo :
En la línea 17 exportamos la función «inicio», con el nombre «inicio». Naturalmente, la forma de usarla cambiara; en nuestro fichero «start.js», deberemos cambiar la llamada.
La utilización de una forma u otra, solo viene condicionada por las necesidades de cada caso. Con ambas formas, todo lo que no se está importando queda oculto, como privado del módulo exportado, aunque esos detalles los veremos mas adelante.
Los módulos y los ficheros
Si hemos dicho que los módulos son ficheros, deberemos tener en cuenta donde los guardamos, y después, deberemos indicar los path correctamente cuando hagamos los «require».
En el ejemplo anterior nos referíamos a un módulo que se encontraba en un fichero en la misma ruta del que llamaba; por eso nos bastaba con indicarle:
var server = require(‘./server.js’)
Tambien podemos indicar rutas absolutas, aunque pienso que no es demasiado correcto, mas que nada, por la dificultad de mantenimiento. Solo tenemos que escribirlo directamente.
En windows seria:
var server = require('C:\\Program Files\\aplicacion\\server.js')
En linux, podríamos escribir
var server = require('/home/usuario/aplicacion/server.js')
En cada caso, utilizaremos los separadores correspondientes al SO; aunque en el caso de windows, al ser su separador la ‘\’ que tiene también la funcionalidad de carácter de escape, debemos utilizarla duplicada.
Igual que utilizamos el ‘.’ para referirnos al directorio actual, podemos utilizar el ‘..’ para referirnos al directorio superior al actual.
En caso que no se encuentre el fichero, se lanzara un error ‘MODULE_NOT_FOUND’
Buscando node_modules
Cuando hacemos una llamada a «requiere» indicando solo el nombre del fichero, incluso sin extensión, lo primero que hace es comprobar si el nombre facilitado corresponde a algún modulo del core; si no es asi, le añade la extensión «.js» y comprueba que no exista en el directorio actual, y si no es asi, busca en el directorio padre una carpeta llamada node_modules y dentro de ella, el fichero solicitado; si no lo encuentra, sigue repitiendo esa búsqueda subiendo directorio en directorio.
Por ejemplo, supongamos que estamos trabajando en el fichero:
/home/usuario/aplicacion/node/servicios/atencion.js
y, en ese fichero, hacemos
var aut = requiere('aut')
Se realizará búsqueda de los siguientes ficheros:
/home/usuario/aplicacion/node/servicios/node_modules/aut.js /home/usuario/aplicacion/node/node_modules/aut.js /home/usuario/aplicacion/node_modules/aut.js /home/usuario/node_modules/aut.js /home/node_modules/aut.js /node_modules/aut.js
Hasta que se encuentre. Esto nos deja claro que si indicamos las rutas relativas de nuestros módulos, mejorará el rendimiento de nuestro servidor; y por razones históricas, la mejor opción es dejar nuestros módulos en la carpeta «node_modules»
Adicionalmente, Node puede buscar el módulo en:
- 1:
$HOME/.node_modules
- 2:
$HOME/.node_libraries
- 3:
$PREFIX/lib/node
Siendo $HOME
el directorio raíz del usuario, y $PREFIX el valor que se haya fijado en la configuración para node_prefix
.
Con lo que sabemos hasta ahora, deberemos crear en nuestra aplicación una carpeta «node_modules» y mover a ella nuestro primer módulo «server»
Y modificar el «requiere»
indicandole la carpeta en la que se encuentra, o solo el nombre del módulo
Incluso, si quereis, sin la extensión
….lo encontrará igual, aunque deberemos tener cuidado que el nombre que estemos utilizando, no coincida con alguno de los que vienen con Node,ya que en dicho caso, no se ejecutara nuestro módulo, ya que los del core tienen preferencia.
Resumen final de la resolución de «require»
En el manual de Node.js, en la pagina https://nodejs.org/api/modules.html hay un resumen que me he permitido copiar aqui, traduciendolo un poco,pero que os aconsejo que vayais a esa pagina para aclararos las dudas.
require(X) en un módulo que esta en la ruta Y
1. Si X es un módulo del core,
a. return el módulo
b. STOP
2. Si X empieza por './' o '/' o '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"
LOAD_AS_FILE(X)
1. Si X es un fichero, carga X como text/javascript. STOP
2. Si X.js es un fichero, carga X.js como text/javascript. STOP
3. Si X.json es un fichero, parsea X.json a JavaScript Object. STOP
4. Si X.node es un fichero, carga X.node como addon. STOP
LOAD_AS_DIRECTORY(X)
1. Si X/package.json existe ,
a. Parsea X/package.json, y busca un valor "main" .
b. let M = X + (json main field)
c. LOAD_AS_FILE(M)
2. Si X/index.js existe, carga X/index.js como text/JavaScript. STOP
3. Si X/index.json existe, parsea X/index.json a JavaScript object. STOP
4. If X/index.node existe, carga X/index.node como addon. STOP
LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
c. DIR = path join(PARTS[0 .. I] + "node_modules")
b. DIRS = DIRS + DIR
c. let I = I - 1
5. return DIRS
El cacheo
Para mejorar el rendimiento, Node.js cachea los módulos la primera vez que los carga. Eso permite que sucesivas llamadas a un mismo módulo no repitan la posible ejecución del código que contiene el módulo internamente.
Si necesitamos que una parte del código se ejecute cada vez que se carga, deberemos exportar esa parte como función, y ejecutar dicha función
En nuestro siguiente articulo, empezaremos a ver como analizar las rutas pasadas, y como servir ficheros
Relacionado
Descubre más desde Recursos para formacion
Suscríbete y recibe las últimas entradas en tu correo electrónico.