• No results found

Descubriendo Nodejs Express

N/A
N/A
Protected

Academic year: 2021

Share "Descubriendo Nodejs Express"

Copied!
172
0
0

Loading.... (view fulltext now)

Full text

(1)
(2)

Descubriendo Node.js y Express

Aprende a desarrollar en Node.js y descubre cómo

aprovechar Express

Antonio Laguna

Este libro está a la venta enhttp://leanpub.com/descubriendo-nodejs-express Esta versión se publicó en 2013-07-02

This is aLeanpubbook. Leanpub empowers authors and publishers with the Lean Publishing process.Lean Publishingis the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do.

(3)

¡Twitea sobre el libro!

Por favor ayuda a Antonio Laguna hablando sobre el libro enTwitter! El tweet sugerido para este libro es:

¡Acabo de hacerme con Descubriendo Node.js y Express! #descubriendoNodejs El hashtag sugerido para este libro es#descubriendoNodejs.

Descubre lo que otra gente está diciendo sobre el libro haciendo click en este enlace para buscar el hashtag en Twitter:

(4)

También por

Antonio Laguna

Laravel: Code Happy (ES)

(5)

Índice general

Introducción . . . . i

Dedicado a… . . . i

Errare humanum est . . . . i

Feedback . . . i

Libro en desarrollo . . . ii

Introducción . . . iii

Evolución de Node.js . . . v

Algunas presunciones . . . v

Audiencia del libro . . . vi

Introducción a Node.js

. . .

1

Node.js basado en eventos . . . . 2

La asincronía por naturaleza . . . . 3

Instalando Node.js . . . . 5

Instalando en Windows y Mac . . . 5

Instalando en Linux . . . 6

¿Funciona mejor Node.js en algún sistema? . . . 7

¿Qué acabamos de instalar? . . . 7

Accediendo a la consola . . . 8

¡Hola mundo! . . . . 9

Hola mundo… ¡en un servidor! . . . 10

La consola de Node . . . 15

console.logyconsole.info. . . 15

console.erroryconsole.warn . . . 17

console.timeyconsole.timeEnd . . . 17

Accediendo a las variables del entorno . . . 19

(6)

ÍNDICE GENERAL

NPM - Node Packaged Modules . . . 23

Búsqueda de paquetes . . . 23

Obtener información de paquetes . . . 24

Lista de paquetes instalados . . . 24

Instalación de paquetes . . . 25

Desinstalación de paquetes . . . 27

Paquetes útiles y habituales . . . 27

Dudas frecuentes . . . 27

Cómo mantener Node.js actualizado . . . 29

Sobre las versiones de Node.js . . . 30

Nuestra primera aplicación de Node.js . . . 31

Resumen . . . 34

Adentrándonos en Node.js

. . .

35

Gestión de dependencias conpackage.json . . . 36

Versionado semántico . . . 37

Estructura del archivo . . . 38

Exportando en Node.js . . . 42

Exportando con el objetoexports . . . 42

Exportando conmodule.exports . . . 43

Algunas aclaraciones . . . 45

Pasando parámetros arequire . . . 47

Organizando el código de nuestra aplicación . . . 49

El archivo de configuración . . . 50

Emisión de eventos conEventEmitter . . . 53

Patrón del observador . . . 53

Emitiendo eventos con Node.js . . . 53

Pasando parámetros a los eventos . . . 54

Dejando de escuchar eventos . . . 55

Refactorizando el ¡Hola mundo! . . . 55

Creando clases que emiten eventos . . . 56

Un ejemplo real . . . 58

Los Streams en Node.js . . . 60

¿Que es un Stream? . . . 60

La funciónpipe . . . 61

(7)

ÍNDICE GENERAL

Escritura -writable . . . 63

Lectura y Escritura -Duplex . . . 66

Transformación -Transform . . . 66

Pasarela -PassThrough . . . 67

El sistema de archivos . . . 68

Leyendo ficheros . . . 68

Escribiendo en ficheros . . . 69

Los Streams y los ficheros . . . 70

Resumen . . . 72

Introducción a Express

. . .

73

Otros frameworks de Node.js . . . 74

Meteor . . . 74

Derby . . . 74

flatiron . . . 75

TowerJS . . . 75

¿Por qué Express? . . . 76

Instalaci�n de Express . . . 77

Creando la estructura básica . . . 78

Welcome to Express - Bienvenido a Express . . . 80

Configuración de la aplicación . . . 83

Guardando y obteniendo valores en la aplicación . . . 83

Configurando la aplicación . . . 84 Rutas . . . 87 Parámetros . . . 90 Cadena de búsqueda . . . 93 Middlewares . . . 95 app.use . . . 95 En línea . . . 97 Mapeado . . . 98 En resumen . . . 98

Middlewares ofrecidos por Express . . . 99

La petición -request . . . 102

req.body . . . 102

(8)

ÍNDICE GENERAL req.is(tipo) . . . 103 req.ip . . . 103 req.xhr . . . 103 La respuesta -response . . . 104 res.status . . . 104 res.redirect . . . 104 res.send . . . 105 res.jsonp . . . 105 res.sendfile . . . 106 res.download . . . 106 res.render . . . 107

Plantillas con Jade . . . 108

Sintaxis básica . . . 109

Anidando elementos . . . 112

Variables en Jade . . . 112

Bloques de código auxiliares . . . 115

Páginas de error en Express . . . 118

Gestión de Login con Passport . . . 120

Gestionando la subida de ficheros . . . 129

Subiendo varios ficheros . . . 133

Resumen . . . 136

Apéndice A: Ejecuta tu aplicación Node.js “siempre”

. . . .

138

Ejecutando Node.js en segundo plano . . . 139

Usandoforever . . . 140

Operaciones con los procesos . . . 141

Consejo extra . . . 143

Apéndice B: Creando un chat con Socket.io

. . . .

144

¿Qué es Socket.io? . . . 144

La aplicación que vamos a crear . . . 145

Instalando las dependencias . . . 146

El lado servidor . . . 146

(9)

Introducción

Dedicado a…

A Laura, mi mujer. Ella me ha apoyado e impulsado a hacer esto posible. Sin ella, estoy seguro de que este libro no habría tenido lugar. Además, ha tenido a bien el crear la (para mi) maravillosa portada que da presencia al libro.

A mi padre. Él no solo me ha animado, si no que puso la semilla de la programación en mi y ese gusanillo de pegarte horas delante del monitor, apasionado por la programación.

Por supuesto a Ryan Lienhart Dahl, creador de Node.js que ha hecho que toda esta revolución sea posible.

A David López, por su inestimable ayuda ofreciendo un valiosísimo feedback con cada capítulo/sec-ción/coma/espacio/trozo de código/etc que he ido publicando. ¡Gracias!

A la comunidad, Node.js no sería lo que es de no ser por esa gran cantidad de paquetes y apoyo que recibe por parte de la comunidad.

Errare humanum est

O como dicen en mi pueblo, el que tiene boca se equivoca.

Me considero una persona bastante cuidadosa con la escritura y bastante obsesionado con las faltas de ortografía y gramática. Eso no quita, que se me pueda haber escapado algo y seguramente, así será. Si te encuentras con cualquier error en el libro, tanto de escritura como de código, te agradecería que me avisaras enviándome un correo [email protected]¹incluyendo el capítulo o frase relevante.

Feedback

¿Tienes alguna crítica constructiva? ¿Quieres hacerme algún comentario? ¿Crees que alguna sección podría ser mejorada? ¿Me quieres enviar un jamón? Para todo eso, y mucho más, envíame un correo [email protected]².

¹mailto:[email protected]

(10)

Introducción ii

Libro en desarrollo

¿Pero esto qué es? ¿¡He comprado un libro que no está terminado?! Me temo que sí. ¿Por qué he hecho esto? Pues porque me gustaría nutrirme del feedback que vayáis pudiendo ofrecerme sobre el libro conforme se va escribiendo y así poder ofrecer un libro que sea lo más útil posible al lector. Planeo escribir el libro en tres tandas. Tanto en la primera como en la segunda, estará con un precio reducido para incentivar su adquisición. Ten en cuenta que una vez te hagas con el libro, podrás hacerte con todas las actualizaciones que este tenga, incluso me encargaré de que te llegue un correo avisándote del hito.

Si te has aventurado a hacerte con el libro durante su gestación, gracias. De verdad. Ponte en contactoconmigo³y hazme saber qué te parece. ¡Como agradecimiento te colocaré en los créditos! Actualmente esto es lo que está en desarrollo:

• Apéndice A - Uso de Socket.io y aplicación básica

• Apéndice B - Uso de conexión contra BD… ¿Mongo? ¿MySQL? ¿Ambos?

(11)

Introducción

Esto que lees, son las primeras palabras de mi primer libro, ¡un gran hito! Le he dado bastantes vueltas a esto de la introducción así que espero que no quede tan mal después de todo.

Quizá te estés preguntando, ¿y quién es este para enseñarme Node.js?

Quizá no tenga experiencia con los libros, pero llevo bastante tiempo en la red intentando esparcir mi conocimiento y, hasta ahora, ¡no me ha ido mal! Quizá hayas leído alguno de los tutoriales de programación que escribí enFunción 13⁴, mi web. O quizá, te hayas cruzado con alguna de mis guías de World of Warcraft en una página de cuyo nombre no quiero acordarme. En cualquier caso… me apasiona enseñar, y me apasiona el desarrollo, principalmente el desarrollo web. Es por ello que te advierto que no encontrarás largas explicaciones ni frases rebuscadas, suelo ser bastante directo aunque por ello aparente que no hay tanto contenido.

Voy a hablar un poco de mi, puedes saltártelo si no te interesa… lo entendería…

¿Aun sigues aquí? Entonces es que quieres leer algo sobre mi. Intentaré mantenerlo breve. Soy Antonio Laguna y soy programador web. Original de un pequeño pueblo del Aljarafe sevillano, en España. Desde pequeño tuve la suerte de trastear con los ordenadores. Con mi padre como programador desde que la informática se inició, he tenido siempre a mano algún ordenador. Recientemente me he mudado a Londres que, como espero que sepas, es la capital de Reino Unido para trabajar en Gamesys. Mi empresa se dedica a realizar páginas de juegos de casino: ruleta, cartas, tragaperras, bingo, etc. Tengo la suerte de trabajar con un gran equipo de profesionales de los que estoy aprendiendo día a día. Mi trabajo no es diseñar las webs, es hacer que éstas cobren vida, gracias a JavaScript principalmente.

Fue hace unos años ya que empecé a picarme con Node.js. Tenía una necesidad que cubrir en mi anterior empresa, Accenture y todo lo que leía apuntaba a Node.js. Viniendo de PHP y con algunos conocimientos básicos sobre JavaScript, me amarré a esa frase del “¿quién dijo miedo?” y aquí estamos. En mi tiempo libre me encanta leer sobre desarrollo y escribir en mi blog. Pero dejemos de hablar de mi, he venido a hablar de mi libro… digo de Node.js.

Node.js es una gran revolución. ¿JavaScript en el lado del servidor? ¿Quién iba a pensarlo? JavaScript lleva mucho tiempo entre nosotros y ha evolucionado muchísimo como lenguaje y, por suerte, sigue haciéndolo.

Vale… pero, ¿qué es Node.js?

Node.js es un sistema del lado del servidor, para escribir código que nos permite crear aplicaciones web e incluso servidores web que responden a peticiones. Está creado sobre el motor JavaScript que lleva Chrome (V8), lo cual lo hace realmente rápido.

(12)

Introducción iv Según la página de Node.js, esta es la definición:

Node.js es una plataforma creada sobre el motor JavaScript de Chrome para crear aplicaciones de red rápidas y escalables. Node.js utiliza un modelo basado en eventos y entrada/salida que no bloquea, lo cual lo hace ligero y eficiente, perfecto para aplicaciones que usen muchos datos en tiempo real que puedan ejecutarse de forma distribuida en varios dispositivos.

Prometedor… ¿no? Además, puede que te interese saber que compañías como Microsoft, Linkedin o Yahoo ya están usando Node.js para el software.

¿Un servidor?

Sí, has leído bien. Node.js es capaz de crear un servidor web y no tendrás la necesidad de usar algo comoApache⁵,lighthttpd⁶oNginx⁷.

Pufff… ¡qué complicado!

¡No! ¡No lo es! Y eso es lo que pretendo demostrarte en este libro. Todas las personas que conozco que han comenzado con Node.js, han acabado disfrutando mucho del entorno porque tienes muchísima libertad a la hora de escribir código y sientes que todo está en tus manos.

Para que te hagas una idea, crear un servidor ocupa tan solo seis líneas de código… ¡como mucho!

1 var http = require('http');

2

3 var server = http.createServer(function (request, response) {

4 response.writeHead(200, {"Content-Type": "text/plain"});

5 response.end("¡Hola Mundo!\n");

6 }).listen(8080);

7

8 console.log('Servidor escuchando por el puerto 8080');

Tampoco quiero agobiarte ahora al principio, pero creo que es un código bastante sencillo de entender.

Una de las mejores cosas que tiene Node.js son las librerías que puedes instalar y usar en tus propios desarrollos. He aquí un breve listado:

⁵http://httpd.apache.org/

⁶http://www.lighttpd.net/

(13)

Introducción v • Forever - Te permite ejecutar una aplicación Node.js para siempre, en caso de que algún error

acabe con ella, forever se encargará de levantarla nuevamente.

• Express - La veremos en este libro pero nos permite crear un servidor web y hacer virguerías con él como responder a distintos verbos HTTP, ejecutar código antes y/o después de cada ruta, etc.

• Socket.io - Comunicación en tiempo real con el navegador a través de WebSockets si están disponible, o algunas soluciones menos rápidas en caso de ser otro navegador (Internet Explorer).

• Jade - Un sistema de plantillas usado por Express que nos evita tener que escribir mucho código para crear HTML.

Evolución de Node.js

Node.js ha ido cambiando muchísimo desde que apareció “al público general”. Poco a poco ha ido revolucionando la tecnología y más y más empresas se animan a usar Node. Lo bueno, es que gracias a su versatilidad, puede que estés usando ya algunas herramientas que usen Node… ¡sin saberlo! Una de las cosas malas que tiene Node.js es que está en constante cambio. Aunque ahora están un poco más calmados, al principio particularmente los cambios eran contínuos y la estabilidad algo dudosa. ¡Pero eso ha cambiado! Dado el gran apoyo de muchas empresas y el interés general que existe por Node, cada vez es más estable y robusto y los cambios no suelen ser tan drásticos. Suelen sacar versiones bastante a menudo con la intención de solucionar errores y, especialmente, mejorar el rendimiento. No obstante, a veces, el cambio de versión es bastante significativo e implica que ciertas funciones dejen de funcionar como lo hacían antes. Por eso es muy importante revisar lawiki⁸oel blog⁹antes de actualizar.

Habitualmente, Node.js mantiene dos versiones. Una inestable, que está en continuo desarrollo y no está recomendada para el uso en producción, y otra estable que es la que normalmente descargaremos para nuestras aplicaciones. Aunque ahora mismo no tienes que preocuparte de nada de esto ya que, por regla general, te bastará con la versión estable.

Algunas presunciones

En este libro utilizaremos ejemplos basados en sistemas Unix. Esto no implica que no vayan a funcionar en un entorno Windows, si no que verás comandos como ls que no funcionarán en

Windows. Aunque no es algo que ocurrirá muy a menudo e intento minimizarlo lo máximo posible, tenlo en cuenta si estás siguiendo el libro en Windows.

⁸https://github.com/joyent/node/wiki

(14)

Introducción vi

Audiencia del libro

Este libro está pensado para lectores que tengan algo de experiencia con algún lenguaje de orientación a objetos: Ruby, Python, PHP o Java incluso; algo de experiencia con JavaScript y, por supuesto… ¡nuevos con Node.js!

En este libro no vamos a explicar los tipos de variables, cómo funciona un bucleforo qué valores

se evalúan comofalseen JavaScript. Lamento decirte que, sin estos conocimientos, quizá te sientas

algo perdido.

No obstante, no pretendo que seas un ninja de JavaScript, ni un gurú, ni tururú. Es más, en las cosas especialmente oscuras de JavaScript me detendré si lo veo necesario para ayudarte en el camino del aprendizaje de Node.js y, porqué no, de JavaScript.

Puede que te estés preguntando, ¿todo lo que sé de JavaScript lo puedo usar en Node.js? Sí y no. Lo mismo ocurre a la inversa. Node.js vive en el servidor por lo que no tendrás un objetowindow

ni dispondrás del métodoalert(), a su vez, el navegador no tiene acceso a funciones de ficheros

o a los Streams por ejemplo (sean lo que sean). No obstante, la sintaxis y las palabras claves son exactamente las mismas con la salvedad de que Node.js usa versiones más modernas de JavaScript que solo están disponibles en los últimos navegadores.

Observa que el título del libro indica claramente Descubre. Este no es un libro para convertirte en Maestro, ni en Ninja ni nada por el estilo. Es para ayudarte en el camino del conocimiento. Por la red esparcida hay mucho conocimiento sobre Node.js pero no todo está actualizado y casi todo está desperdigado en diferentes sitios. Mi intención es que comiences conmigo el aprendizaje. Te daré las herramientas y los conocimientos para comenzar a crear tus propias aplicaciones (sean o no web). Bueno… ¿Estás preparado para sumergirte en el mundo de Node.js? ¡Pues adelante, sigue leyendo! ¡Nos vemos en el primer capítulo!

(15)

Introducción a Node.js

En la introducción de el libro ya hemos hablado un poco de Node.js… ¡y hasta hemos puesto un sencillo ejemplo! pero no quiero dejar de profundizar un poco más.

Si eres el tipo de lector al que va dirigido este libro, probablemente no tengas mucha experiencia con JavaScript. Tocas aquí un poco, un poco de jQuery por allí, este módulo de pop-ups por acá y un slideshow por allá. ¿Qué hay en común en todo esto? Que estamos en el cliente, el navegador. Si eres de esos que usan jQuery muy a menudo para hacer animaciones en la web, o seleccionar un elemento de la página, no es con eso con lo que te vas a encontrar aquí.

Node.js es JavaScript del lado del servidor. Realmente es algo más que JavaScript, es un 70% JavaScript y el resto es principalmente C / C++. Es por ello que tienes que intentar cambiar el chip. Quizá te sea más sencillo compararlo con un entorno PHP, Ruby o Python (todos amigos por igual…). Para trabajar con Node.js, nos valdremos de la línea de comandos en muchas ocasiones ya que, en el fondo, no es más que una interfaz de línea de comandos. ¡Te vas a sentir todo un hacker! Sé que muchas personas le tienen miedo a la línea de comandos, pero como dice Bane…

1 Yo nací en la línea de comandos, moldeado por ella. No vi Windows hasta que\

2 ya era un hombre...

Créeme cuando te digo que no tienes por qué preocuparte, ya que no vamos a usar ningún comando raro en ningún caso. ¿Confiarás en mi?

El pilar fundamental de Node.js, es que está basado en eventos y su naturaleza de no bloqueo. No, no estamos hablando del tipo de bloqueo del parchís. Si no de operaciones que bloquean (o no) el servidor. Vamos a meternos un poco más en faena.

(16)

Node.js basado en eventos

La aplicación habitual de Node.js, se queda residiendo en memoria y espera algo por parte del sistema para ejecutar una función. Esto puede ser alguien entrando en una página web, un cambio en un fichero de un directorio o un mensaje que llegue por un socket. Piensa en ello como una gasolinera 24 horas. Está ahí abierta y puede pasar horas sin que nadie vaya, pero eventualmente alguien pasará a repostar y estará lista para surtir gasolina.

¿Y qué hace durante el resto del tiempo? Nada. De hecho es bueno que no haga nada ya que es necesario para que se active el recolector de basura de JavaScript.

¿Basura? ¿Qué pasa si no se recolecta?

Los recolectores de basura existen en la gran mayoría de los lenguajes. Son como eso que imaginas solo que no son personas. Es un proceso que se encarga de revisar el código que está en ejecución y decir…

1 A ver, ¿esta variable sigue existiendo? No, ¿no? Pues la quitamos de la mem\

2 oria

3 ¿Y esta función ha terminado ya? Quitemos todas sus variables de la memoria\

4 .

Estoy seguro, lector, de que ya sabes lo que pasa si no recolectamos la basura. Que, eventualmente, nos quedaríamos sin memoria y eso sería una catástrofe. Todo empezaría a ir lento. ¡No solo la aplicación! ¡Si no el sistema!

¿Y puedo yo llamar al recolector de basura?

No, no puedes ni debes. Si seguimos buenas prácticas de programación no tendríamos nunca que preocuparnos por este proceso invisible.

Vale Antonio, ¿pero todo esto no lo puedo hacer con Python o PHP?

Seguro que estás pensando en eso. Mucha gente lo piensa, especialmente los Javasaurios. Y tienes razón. Node.js no es la panacea y no hará todo el trabajo por ti. Es una herramienta que, en manos inexpertas puede parecer poca cosa. En este libro vamos a intentar aprovechar todo ese potencial que está dando tan buenos resultados por ahí.

Node.js es especialmente bueno cuando queremos hacer cosas a la vez. ¿No te has visto en la tesitura nunca de decir, ojalá pudiera hacer cosas en paralelo? Pues en Node.js eso es lo que ocurre. Bueno, más o menos. Vas a tener que confiar en mi, un pequeño salto de fé. Si lo hiciste con Altair, ¡seguro que puedes lograrlo!

(17)

La asincronía por naturaleza

En Node.js hay dos formas de hacer las cosas. Asíncronas o síncronas.

Valiente perogrullada… ¡No me aclaras nada!

Espera espera… Voy a ponerte un ejemplo. Imagina que vas a prepararte el desayuno. Tienes hambre. Vas a hacer café y tostadas. En un mundo síncrono, meterías la tostada. Cuando saliera del tostador, comenzarías a hacer el café. Cuando el café saliera de la cafetera, untarías la tostada de mantequilla. Cuando terminaras calentarías algo de leche. Finalmente te podrías tomar el desayuno solo que, probablemente, el café que te eches en la taza esté un poco frío y la tostada esté fría al untarle la mantequilla.

En un mundo asíncrono la cosa cambia. Pones la cafetera y, mientras se está haciendo el café, calientas la leche y pones la tostada a tostarse. Para cuando termines de hacer la tostada probablemente ya tengas el café preparado y esté todo listo para tomarse.

Veámoslo ahora con un ejemplo de código:

Ejemplo 1: Código tradicional síncrono

1 var resultado = db.query("SELECT * FROM usuarios");

2 // Esperamos a los resultados

3 hacerAlgoConEllos(resultado); // Esperamos a que termine

4 hacemosOtraCosa();

Ejemplo 2: Código asíncrono

1 db.query("SELECT * FROM usuarios", function(resultados){

2 hacerAlgoConEllos(resultado); // Esperamos a que termine

3 });

4 // Esta función se ejecuta justo después de que se haya lanzado la consulta

5 // antes de obtener los resultados

6 hacemosOtraCosa();

Y… ¿realmente se ejecutan las cosas a la vez? La respuesta es no.

(18)

La asincronía por naturaleza 4 Aquí está el engaño…

Te dije que confiaras en mi. En apariencia se ejecutan a la vez. Sin embargo, tras el telón, lo que realmente pasa es que las callbacks quedan en una pila y se van ejecutando. Hasta que ese callback termine, el resto tendrá que esperar. Lo que ocurre, es que el motor de Node.js es tan rápido y normalmente no usamos procesos tan pesados que, en apariencia, se ejecutan a la vez.

La parte negativa, es que no sabemos tampoco en qué orden se ejecutan. Para los que les gustan las explicaciones técnicas, lo que realmente ocurre es que JavaScript, tanto el cliente como en el servidor, se ejecuta en un único hilo, por lo que es técnicamente imposible que haga dos cosas a la vez. Pero confía en mi, esto no es ningún problema.

Esto puede resultar un poco confuso, especialmente al principio. Pero si me vas siguiendo no deberías perderte en el camino de la asincronía.

(19)

Instalando Node.js

Para no aturdirte en demasía, vamos con algo ahora sencillito. Así vamos intercalando una de cal y otra de arena. Vamos a ponernos manos a la obra y a instalar Node.js para poder empezar a cacharrear que es lo que a todos nos gusta, ¿verdad? Como verás es un proceso realmente sencillo.

Instalando en Windows y Mac

El proceso de instalación en ambos sistemas es exactamente el mismo. 1. Nos dirijimos a la página de Node.js:http://nodejs.org/

2. Le damos al botón grande y verde que pone INSTALL. Esperamos.

3. Una vez finalice la descarga, tendremos un archivo.msio.pkgdepende del sistema en el que

estemos. Lo localizamos y hacemos doble click.

4. Finalmente, seguimos el proceso de instalación que es bastante sencillo. 5. Profit.

(20)

Instalando Node.js 6

Figura 1: Instalación de Node.js en Mac OSX

Instalando en Linux

Cubrir cada distribución de Linux es una locura, pero el proceso no debería variar mucho. En este caso, vamos a ver cómo instalar Node.js en Ubuntu.

1. Nos dirijimos a la página de Node.js:http://nodejs.org/ 2. Le damos al botón de DOWNLOAD.

3. En la siguiente página, tendremos que elegir el código fuente de Node.js que, en el momento en que se escribe el libro, está en el último lugar de la tabla.

4. Una vez descargado, deberíamos colocarlo en la carpeta/usr/local/src.

(21)

Instalando Node.js 7

Descomprimiendo e instalando Node.js

1 tar -zxf node-v0.10.5.tar.gz

2 cd node-v0.10.5

3 ./configure

4 make

5 sudo make install

Atención

Puede que necesites realizarsudopara realizar algunas acciones. Ten en cuenta además,

que el proceso puede llevar algo de tiempo. Si necesitas más información para instalar Node.js en alguna versión de Linux en partícular, revisa las instrucciones de instalación en lawiki de Node.js¹⁰.

¿Funciona mejor Node.js en algún sistema?

Ciertamente donde mejor funciona es en sistemas basados en Unix, sea este Linux o Mac OSX. Instalar Node.js en Windows al principio era un peñazo, por no decir una palabra más fea. Había que usar compiladores y armarse de paciencia.

Por suerte, Microsoft entendió que no se podía quedar atrás en esto, y se alió con Joyent (la empresa detrás de Node.js) para portar Node.js a Windows como Dios manda.

Aun así, hay algunos paquetes que no funcionan en Windows porque tienen dependencias especiales de Unix. Esto no quiere decir que no vayas a poder trabajar… ¡Para nada! De hecho, los ejemplos que encuentres aquí los pruebo siempre en ambos sistemas por lo que no deberías preocuparte para nada.

¿Qué acabamos de instalar?

Seguramente pienses que me he vuelto loco…

¿No estabamos instalando Node.js? ¿Por qué me haces esa pregunta?

(22)

Instalando Node.js 8 La verdad es que sí, que estábamos instalando Node.js. Lo que no te he contado es que además, acabamos de instalar npm. Esto ocurre de forma automática desde la versión0.6.3y es totalmente

transparente.

Ahora mismo no quiero que te preocupes demasiado sobre lo que es npm. ¡No te distraigas! Sigamos la senda del conocimiento… Ohmmm…

Vamos a comprobar qué tenemos. Abre el terminal y escribe lo siguiente:

1 node --version

Si todo fue bien, deberás ver algo como:

1 v0.10.11

¡Bien! Ahora podemos seguir.

Accediendo a la consola

Tanto en Mac como Linux, la consola no es más que el terminal del sistema y suele llamarse Terminal a secas. Especialmente en Linux estarás acostumbrado a usarla de cuando en cuando, pues muchos programas y/o paquetes necesitan del uso eventual de la consola.

No obstante, en Windows es una versión modificada del cmd que nos crea directamente Node.js al instalarla. Esta versión no tiene nada de especial, solo que nos añade algunas variables de entorno y nos inicia automáticamente como administradores, de esta manera podremos ejecutar Node.js con menos fricciones. Seguro que, con paciencia y saliva puedes hacer funcionar la consola normal de Windows como lo hace la de Node.js. ¡Ánimo e inténtalo!

Para acceder a ella no tienes más que ir a la carpeta que el proceso de instalación habrá creado en el menú de inicio:

(23)

¡Hola mundo!

Antes de pasar a explicar nada más, y solo por seguir con la costumbre, vamos a crear nuestro primer “programa” de Node.js y para ello vamos a ver dos formas de hacerlo. Si no te suena para nada esta práctica, ¡debería! Lo que intentamos hacer es, que usando el lenguaje sobre el que estamos aprendiendo, mostremos algo así como un saludo. Normalmente es Hola Mundo! o Hello World! en Inglés.

Primero escribenodeen la consola.

¿Ya? Si todo ha ido bien, debería quedarse con un símbolo>esperando nuestras órdenes. No pdoemos

darle cualquier orden, por ejemplo esto no funcionará:

1 > Di "Hola Mundo"

2 ...

Node no entiende nada y nos devuelve un …. Creo que es su forma de decirnos. ¿En serio? ¿Qué

quieres que haga con eso? Vamos a probar a hablarle en su idioma, JavaScript.

1 console.log('¡Hola mundo!');

Ahora sí, Node nos dirá algo porque es capaz de entendernos:

1 ¡Hola mundo!

2 undefined

¡Bien! ¡Ahora nos saluda! Pero… espera… ¿qué es eso de undefined? Bien. A ver cómo lo explico.

undefinedes solo que la sentencia que acabamos de escribir, no “devuelve” ningún valor. Aunque

seguro que ya lo sabes, ehem, el valorundefinedes como si no hubiera valor alguno. Si alguna vez

has usado la consola de las herramientas de desarrollador de Chrome, verás que el comportamiento es exactamente el mismo.

Vamos a ver qué pasa si ponemos algo que sí devuelva un valor.

1 parseInt('30',10);

Aunque esto también seguro que lo sabes,parseIntintenta transformar una cadena en un número

y lo devuelve así que, en esta ocasión, veremos que nada más darle alEnternos devuelve un30.

(24)

¡Hola mundo! 10 Pero… ¿¡cómo salgo de aquí?!

Upss… casi me olvido. Para salir, pulsaCtrl + C(dos veces) y se cerrará la consola de Node. Esta es

la forma de “terminar un proceso”.

El otro metodo, como pronto descubrirás, es como lo haremos habitualmente, colocando el código en un archivo. No creerías que ibas a tener que estar escribiendo ahí siempre, ¿verdad?

Lo que vamos a hacer, es crear primero una carpeta en la que guardaremos nuestra aplicación.

1 $ mkdir holamundo

2 $ cd holamundo/

Ahora que ya estamos dentro de la carpeta, y si estás en un sistema Unix, puedes hacer lo siguiente para crear un archivo:

1 $ touch app.js

Si no, abre tu editor de texto favorito y crea un archivo en esa carpeta con ese nombre. El nombre deapp.jses solo una convención para indicar que es el archivo que contiene la aplicación y, por

tanto, el “ejecutable”.

Ahora abre el archivo con tu editor de texto preferido (si es que no lo habías hecho ya) y escribe dentro lo siguiente:

1 console.log('¡Hola mundo!');

Guárdalo, y en el terminal escribe:

1 $ node app.js

Esta vez deberíamos ver el mensaje sin elundefinedde antes y, tras aparecer, la aplicación se cerrará

sin más. ¡Fácil! ¿no?

Hola mundo… ¡en un servidor!

¿Recuerdas el ejemplo que pusimos en laintroduccióndel libro? Vamos a revivirlo. ¡Vamos a crear vida! Quita todo el código deapp.jsy escribe lo siguiente:

(25)

¡Hola mundo! 11

Hola mundo en el servidor

1 var http = require('http');

2

3 var server = http.createServer(function (request, response) {

4 response.writeHead(200, {"Content-Type": "text/plain"});

5 response.end("¡Hola Mundo!\n");

6 }).listen(8080);

7

8 console.log('Servidor escuchando por el puerto 8080');

Si ahora lo ejecutas con

1 $ node app.js

Verás que en la consola aparece el mensajeServidor escuchando por el puerto 8080que hemos

puesto en la línea 8. Ahora accede ahttp://localhost:8080y, si todo ha ido bien, deberías ver una

página que dice¡Hola Mundo!.

Veamos el ejemplo línea a línea:

En la primera línea lo que hacemos esrequire. Quizá puedas deducir lo que hace porque tenemos

un verbo bastante similar en castellano. Esta sentencia es la forma que tiene Node.js de cargar los módulos. Es similar a include de PHP, #include de C o import en Python. Quizá te estés

preguntando porqué difiere deincludesi tanto PHP como C usaninclude. El motivo es querequire

es una sentencia común cuando usamosrequire.jsen el navegador para modularizar aplicaciones

JavaScript. Tampoco quiero profundizar mucho en esto porque puede ser un poco complejo. En este caso, lo que estamos requiriendo es el módulo http que, casualmente, es un paquete del

núcleo de Node.js por lo que no necesita que lo instalemos.

Ten en cuenta que…

Aunque es buena idea llamar a las variables que reciben los módulos del mismo modo que se llama el módulo, recuerda que es solo una convención para mantener la cordura. Siempre puedes ponervar ptth = require('http');si quieres volver loca a la gente

que lea tu código.

Lo siguiente que hacemos es crear un servidor valiéndonos de la función createServerque nos

(26)

¡Hola mundo! 12

request, que es la petición, yresponseque es la respuesta que tenemos que enviar. Esa función será

llamada cada vez que alguien entre en la URL de nuestro servidor, así que tenemos que decirle lo que tiene que hacer.

En nuestro caso, le indicamos que la petición debe tener un código200, que es el código HTTP para

decir que la petición es correcta, y que el tipo de contenido que tiene que esperar el navegador es texto plano. Además, finalizamos la respuesta con el métodoend, añadiendo el texto que queremos

devolver.

¿Qué pasaría si no llamáramos a

end

?

Si no llamáramos al método end de la respuesta, la petición nunca terminará y el

navegador acabará por dar un error porque sigue esperando que le enviemos datos. ¿No me crees? ¡Pruébalo y verás!

Antes dije: “en este caso anónima”. Ten en cuenta que este código sería totalmente equivalente y válido:

Función no anónima

1 var http = require('http');

2

3 function gestionaPeticion (request, response) {

4 response.writeHead(200, {"Content-Type": "text/plain"});

5 response.end("¡Hola Mundo!\n");

6 }

7

8 var server = http.createServer(gestionaPeticion).listen(8080);

9

10 console.log('Servidor escuchando por el puerto 8080');

(27)

¡Hola mundo! 13

Función en variable

1 var http = require('http');

2

3 var gestionaPeticion = function (request, response) {

4 response.writeHead(200, {"Content-Type": "text/plain"});

5 response.end("¡Hola Mundo!\n");

6 }

7

8 var server = http.createServer(gestionaPeticion).listen(8080);

9

10 console.log('Servidor escuchando por el puerto 8080');

La función createServer recibe otra como parámetro y se encargará de ejecutarla cuando haya

terminado su trabajo. Esto se conoce como callback. Es un patrón muy común cuando se hacen cosas asíncronas ya que, sabemos cuándo se comienza a ejecutar el código, pero no sabemos cuándo va a acabar.

En Node.js, los callbacks por norma general tienen la siguiente estructura. El primer parámetro de un callback debe ser un error si lo hubiere, en caso contrarionull. A continuación, le siguen el resto

de parámetros.

Espera Antonio, ¿entonces Node.js no está siguiendo su propio patrón?

No es eso. Lo que realmente ocurre es que la función que estamos pasando más que un callback es algo que está a la escucha para cuando llega una petición al servidor. El servidor tiene sus propios callbacks internos a la hora de realizar tareas asíncronas y, si hay un error, se encargará de gestionarlo él por lo que nuestra petición debería llegar sin más.

En la siguiente línea, le decimos por el puerto por el que escuchar, en este caso el8080. Puedes elegir

cualquier otro puerto que no esté en uso. ¿Quién soy yo para decirte que no uses el puerto6969para

tu desarrollo? ¡Nadie!

Como verás, la llamada está encadenada concreateServer. Eso es lo mismo que poner justo debajo…

1 server.listen('8080');

(28)

¡Hola mundo! 14

¿Te has fijado?

Si eres observador habrás visto que detrás decreateServertenemos una llamada a la

funciónlisten. Esto se conoce como encadenamiento de funciones y se logra

devol-viendo siempre el objeto creado, en este caso el servidor. Este tipo de comportamiento se ha hizo especialmente común cuando apareció jQuery.

(29)

La consola de Node

Si habéis estado atentos, habréis visto que hemos estado usandoconsole.logy que, la información

que hemos puesto, aparecía en el terminal mientras ejecutábamos la aplicación.

Si has trabajado con JavaScript (cosa que espero) quizá ya estés acostumbrado aconsolepuesto que

es una forma de mostrar en la consola del Navegador información para ver por dónde va pasando nuestro código.

consolesirve para escribir en la salida estándar y en la de error. Ésta nos ayudará enormemente en la

tarea de saber qué es lo que está pasando en las entrañas de nuestra aplicación sin ser excesivamente complicado como podría ser el hecho de activar un depurador.

Aunque no es algo de lo que, a priori, tengamos que preocuparnos, cabe destacar que escribir en la consola es un método síncrono por lo que, si abusamos brutalmente de ella, estaremos creando bloqueos en nuestra aplicación.

Hay librerías estupendas para registro de eventos y logging en general para Node, comowinston¹¹. No obstante, para el propósito de este libro nos valdremos de las bondades de la consola ya que cubre todas las necesidades de aprendizaje.

console.log

y

console.info

Estas dos funciones hacen exactamente lo mismo, pasar información a la salida por defecto. La primera es la que hemos usado en nuestro ejemplo de Hola mundo. No tiene excesivo misterio:

1 console.log('Gracias por hacerte con este libro');

No obstante, la consola se guarda un par de ases en la manga. Veamos uno de ellos. La consola nos permite formatear la información al más puro estilosprintfde PHP.

Imagina que quieres mostrar el número de planetas que hay en nuestro sistema solar, pero en vez de poner un número ahí en plan soso, con una frase para dotarlo de sentido. Podrías hacer esto:

1 var planetas = 8;

2

3 console.log('Hay ' + planetas + ' planetas'); // Hay 8 planetas

Ya que lo que estamos pasando es, de hecho, una cadena de caracteres. No obstante, ¿no sería mejor tener que evitarnos todos esos+? Yo creo que sí. Vamos a ver cómo lograrlo.

(30)

La consola de Node 16

1 var planetas = 8;

2

3 console.log('Hay %d planetas', planetas); // Hay 8 planetas

Lo que hacemos es pasarle a la consola una cadena, y parámetros extra que sustituirá en orden de aparición. Ten en cuenta que si pasas más parámetros de los que realmente pones, Node.js símplemente lo pondrá al final.

1 var planetas = 8,

2 expulsado = "Plutón";

3

4 console.log('Hay %d planetas',planetas,expulsado); // Hay 8 planetas Plutón

Vamos a arreglarlo, pasando un parámetro más:

1 var planetas = 8,

2 expulsado = "Plutón";

3

4 console.log('Hay %d planetas porque %s ya no es uno de ellos',planetas,expu\

5 lsado);

6 // Hay 8 planetas porque Plutón ya no es uno de ellos Como ves, ahora hemos puesto la cadena en su sitio.

Vale, ¿pero qué es eso de%dy%s?

Me alegra que lo preguntes… ¡oh espera! Esos valores son patrones que podemos usar para sustituir cadenas. ¡Hay más!

Patrón Tipo

%d Enteros y coma flotante %s Cadenas

%j Objetos JSON

Vale, no es que sean muchos más, pero al menos ahora tenemos una idea. Vamos a ver qué ocurre si le damos un objeto a la consola.

(31)

La consola de Node 17 1 var sistema_solar = { 2 planetas : 8, 3 expulsarPluton : function() { 4 ... 5 } 6 }; 7 8 console.log(sistema_solar);

9 //{ planetas: 8, expulsarPluton: [Function] }

Como ves, intenta convertirlo a JSON y mostrarnos tanto sus propiedades como métodos para que podamos evaluar, a simple vista, el valor del objeto.

console.error

y

console.warn

Estas funciones son equivalentes y hacen lo mismo quelogeinfosalvo que en vez de a la salida

por defecto, lo envían a la de errores. ¿Qué es eso de la salida de errores?

La salida de errores es una salida alternativa. Esto permite más flexibilidad puesto que puedes tener dos tipos de logs. Uno para errores (que serán importantes) y otro de información (más trivial). Esto es especialmente útil cuando tienes multitud de mensajes mostrándose por tu aplicación y tú solo quieres centrarte en los problemáticos.

console.time

y

console.timeEnd

Estas funciones las usaremos para hacer pruebas de rendimiento de nuestro código. La primera función es como si agarráramos un cronómetro, lo pusiéramos a 0 y empezáramos a contar.

1 console.time('Operación costosa');

2 // Aquí realizamos una… operación costosa

3 console.timeEnd('Operación costosa');

timeEndes como si paráramos ese cronómetro, miráramos el tiempo y lo anunciáramos al mundo.

(32)

La consola de Node 18

1 Operación costosa: 33ms

Esta es una forma realmente conveniente de saber dónde podemos tener algún cuello de botella en nuestro código.

(33)

Accediendo a las variables del

entorno

Quizá ni siquiera sepas lo que es una variable de entorno. No te avergüences. Es una cosa que hoy en día ya casi no se aprender ya que no son tan necesarias como antiguamente. No obstante, en sistemas Unix aun se usan bastante en desarrollo. Si no sabes lo que son, voy a intentar definirlas.

Una variable de entorno es una variable que es almacenada por el Sistema Operativo y que puede afectar a la forma en que se ejecutan los procesos del sistema.

Esto es, son variables que el sistema nos permite configurar y que pueden modificar cómo actúa en sí el sistema.

Una de las variables más conocidas es elPATH, en la que se almacenan las rutas de los ejecutables.

Si una ruta está definida en esa en los sistemas Unix por ejemplo. Si tienes una ruta en esa variable, podrás ejecutar una aplicación sin necesidad de ir a donde está ubicado.

Definir una variable de entorno es realmente sencillo:

1 // Unix

2 NUESTRA_VARIABLE="Su valor"; EXPORT NUESTRA_VARIABLE

3 // Windows

4 set NUESTRA_VARIABLE="Su valor"

En sistemas Unix tenemos además la oportunidad de crear una variable que solo será visible dentro de Node.js, en esa ocasión que la lancemos.

Lo más habitual es establecer la variableNODE_ENV, que establece el tipo de entorno en el que estamos

trabajando que normalmente seráproduction(producción) odevelopment(desarrollo):

1 NODE_ENV=production node app.js

Todas las variables del entorno están accesibles desde el objeto env, que forma parte del objeto process. De esta manera, si queremos por ejemplo cambiar el puerto en el que vamos a ejecutar

(34)

Accediendo a las variables del entorno 20 1 var puerto = 80; 2 3 switch(process.env.NODE_ENV) { 4 case 'production': 5 puerto = 8080; 6 break; 7 case 'development': 8 puerto = 8888; 9 break; 10 }

¡Recuerda!

Las variables de entorno definidas de esta forma son temporales y, o bien desaparecen al cerrar la aplicación, o bien al reiniciar el equipo. Si quieres añadir las variables de forma permanente, tendrás que valerte de/.bash_profileen sistemas Unix o cambiarlas en

(35)

Pasando parámetros a Node.js

Además de valernos de las variables del entorno, podemos pasarles parámetros a Node.js de la siguiente forma:

1 $ node app.js [argumentos]

Este tipo de técnicas es especialmente útil si, en vez de crear un servidor, creamos algún tipo de aplicación que haga un proceso en función de uno o varios parámetros. Por ejemplo, imagina un pequeño script que compare dos ficheros de texto y cree un tercero con las diferencias. En ese caso, podrías pasar los dos nombres de los ficheros a comparar y, un posible tercer parámetro, que contenga el nombre del archivo diferencial que se genere Esos argumentos van separados por espacios y quedan almacenados dentro del objetoargv, que forma parte de process. No obstante,

hay dos valores fijos dentro del objeto: 1. node

2. El nombre del script que estamos ejecutando. Por ejemplo:

/Users/antonio.laguna/proyectos/nodetest/app.js

En la mayoría de las ocasiones, estos argumentos no nos interesan para nada. Por ello, podríamos hacer algo así:

1 var argumentos = process.argv.splice(2);

Por si no estás familiarizado consplice, lo que hace es en ese caso recortar la matriz y dejar lo que

queda a partir del elemento2. Dado este código:

1 var argumentos = process.argv.splice(2);

2 console.log(argumentos);

Si llamáramos a la aplicación de esta forma:node app.js uno dos tresel resultado sería:

(36)

Pasando parámetros a Node.js 22 Ya que ha eliminado los dos primeros iniciales, que no nos interesaban.

De interés…

En caso de que quieras crear un programa de consola, al que le puedas pasar varios parámetros, un buen módulo que he usado en alguna que otra ocasión con bastante éxito esOptimist¹². Una librería que te permite parsear opciones, añadir alias, parámetros obligatorios, menú de ayuda automático, etc.

(37)

NPM - Node Packaged Modules

Comoya hemos comentado, npm es instalado con Node.js de forma automática. Sí, sin que tengamos que hacer nada de particular. Lo bueno es que cuando actualicemos Node.js, npm lo haga también de forma automática.

Vale Antonio, ¿pero me vas a explicar qué es eso de npm?

npm es el gestor de paquetes de Node. Nos sirve para realizar cualquier actuación con paquetes de node. Buscarlos, instalarlos, actualizarlos, etc. Es posible que hayas utilizado algún gestor de paquetes con anterioridad. Los hay para varios sistemas:

• PHP - Composer • Python - Pip • Ruby - RubyGems • OS X - Homebrew

Vamos a ver cómo podemos hacer algunas de estas operaciones con npm. Especialmente las más útiles.

Búsqueda de paquetes

En ocasiones querremos buscar algo. No sabemos cómo se llama el módulo pero sabemos que queremos algo para gestionar… uhmm… ¡asincronía! Si el programador del paquete lo ha hecho bien, debería haber escrito esa palabra en las palabras claves. Dado que somos unos frikis sin remedio, vamos a buscarlo desde la consola. Para ello no tenemos más que escribirnpm search {palabra a buscar}. Por ejemplo:

1 $ npm search async

Esto comenzará a aparecer por pantalla:

{lang=text∼∼∼∼∼∼∼ NAME DESCRIPTION

abiogenesis Asyncronous, (…) actor Experimental (…) advisable Functional (…) aegis Asynchronous (…) aejs Asynchroneous (…) aemitter async emitter (…) ajs Experimental (…) ake A build tool (…) alf Asynchronous (…)∼∼∼∼∼∼∼

Como ves, la lista no es de gran ayuda. Ten en cuenta que esto nos soltará una lista de todos los paquetes que contengan esa palabra en su descripción y/o nombre, por lo que lo mejor es saber de

(38)

NPM - Node Packaged Modules 24 antemano qué vamos a usar. Pero, por lo menos, hemos satisfecho nuestro orgullo friki y hemos buscado paquetes desde la línea de comandos. ¡Estás hecho un hacker!

Aunque no sea tan emocionante, puedes hacer la misma búsqueda enhttps://npmjs.org/ya que es dondenpm searchbusca sus paquetes

Obtener información de paquetes

Ahora que tenemos una lista de paquetes, seguro que quieres saber algo más de los paquetes. Yo, que soy muy curioso, tengo ganas de saber qué hace el paqueteabiogenesis. No es que lo conozca,

lo prometo. Es que es un nombre rarísimo. Para saber los detalles de un paquete, escribiremosnpm

view {nombre del paquete}.

1 $ npm view abiogenesis

Esto realmente nos devuelve una visualización del archivopackage.json. No te preocupes mucho

por él ahora mismo, lo veremos en breve. Ya sé que tienes curiosidad, así que te voy a poner un pequeño fragmento:

1 { name: 'abiogenesis',

2 description: 'Asyncronous, nested \'task\' runner framework with dependen\

3 cy resolution.',

4 'dist-tags': { latest: '0.5.0' },

Vaya, ¡es un fantástico framework que ejecuta tareas asíncronas y anidadas con resolución de dependencias! ¿Tendrá ziritione?

Lista de paquetes instalados

En ocasiones querrás ver la lista de paquetes que tienes instalados en tu aplicación. Para ello, solo tenemos que ejecutar un sencillo comando:

1 $ npm ls

(39)

NPM - Node Packaged Modules 25

1 /Users/antonio.laguna/projects/nodetest

2 └─┬ [email protected]

3 └── [email protected]

Esta lista nos muestra los paquetes en forma de árbol. Como ves, nos muestra que en mi proyecto tengo instalado less, cuya versión es1.3.3. Abajo, tenemos otro paquete,ycssmin. Este paquete,

por el gráfico, podemos saber que es una dependencia deless. Esto es,lessnecesita anycssminpara

funcionar. Como veremos ahora, cuando instalamos un paquete, npm se trae todas sus dependencias. Ahora también hablaremos de los paquetes globales. Basta decir con que si quieres ver una lista de todos los paquetes que tienes instalados a nivel global, solo tienes que hacer algo así:

1 $ npm ls -g

Y verás todos los paquetes globales que tienes instalados, con sus dependencias por supuesto.

Instalación de paquetes

Antes de meternos de lleno a instalar paquetes como cosacos, vamos a hablar sobre el tipo de instalaciones. Ya las hemos dejado caer un poco en la anterior sección pero… allí vamos. Tenemos dos tipos de instalaciones: La instalación global y la instalación local.

Veamos la diferencia.

Los paquetes locales son aquellos que se instalan sobre la aplicación en la que estás trabajando en el momento en que ejecutas el comando. Si por lo que sea la instalas en una carpeta que no debías, se instalará igualmente puesto que npm no distingue si estás o no en una aplicación. Los paquetes locales solo estarán disponibles en el paquete actual. Normalmente es la forma más habitual de instalar un paquete.

Para instalar un paquete localmente, solo tenemos que ejecutar el siguiente comandonpm install {nombre del paquete}. Por ejemplo:

1 $ npm install less

Ahora tu proyecto, podrá hacervar less = require('less');y comenzar a usar sus funciones.

Ten en cuenta que no puedes usar paquetes externos que no hayas instalado.

Por el contrario, habrá veces que el paquete venga con funcionalidad extra o, directamente, sea un programa de la línea de comando. En esos casos tendremos que instalarlo de forma global. Hacerlo es realmente sencillo ya que únicamente tenemos que añadir un distintivo :npm install -g {nombre del paquete}. Por ejemplo:

(40)

NPM - Node Packaged Modules 26

1 $ npm install less -g

Ten en cuenta que el instalar un paquete de forma global no hace que éste esté disponible dentro de todas las aplicaciones usandorequire().

Cómo decidir qué tipo de instalación realizar

Piensa que, en general, una instalación global no es algo bueno. Seguro que, trabajando con JavaScript has leído que las variables globales son malas. Las instalaciones globales… también. Bueno, no es que sean malas, solo que es algo que no tendríamos que tomar a la ligera.

Entonces, ¿cómo puedo decidir? Veamos unos consejos:

• Si quieres instalar un paquete que funcione dentro de tu aplicación conrequire(), instálalo

de manera local.

• Si estás instalando un paquete que puede ser usado desde la línea de comandos como un programa o algún uso extendido (como en el caso de Express), instálalo de manera global. Algunos de los paquetes que suelen instalarse de manera global:

• Express • forever • nodemon • Bower • Grunt • Uglify-js

Webs de instalación de paquetes

Algunos usuarios han decidido mejorar las, ehem, bondades de npm search creando algunas

herramientas realmente útiles.

Una web realmente útil a la hora de instalar paquetes es Nipster¹³. Esta herramienta te permite visualizar un ranking de los paquetes en Github, permitiéndote ordenarlos por Fecha de Modificación (útil para saber si siguen o no activos), número de forks, estrellas, etc.

Como alternativa a Nipster, encontramos Gitmoon¹⁴, que nos ofrece mucha más información de la que podamos encontrar en Nipster sobre cualquier paquete que queramos buscar como la dependencia entre proyectos, quién usa el paquete, etc.

Si descubres (¡o creas!) alguna web que creas que puede cumplir con estas funciones, ¡házmelo saber!

¹³http://eirikb.github.io/nipster/

(41)

NPM - Node Packaged Modules 27

Desinstalación de paquetes

Desinstalar un paquete es tan sencillo como instalarlo. Durante el desarrollo es normal probar paquetes, puede que luego no te guste, no cumpla con tus expectativas o, directamente, no lo necesites y lo hayas instalado porque tenía un nombre divertido. Yo lo sé porque me lo ha contado un amigo. El comando es bastante sencillo… npm uninstall {nombre del paquete} o npm uninstall -g {nombre del paquete}si queremos desinstalarlo globalmente. Por ejemplo:

1 $ npm uninstall -g less

Esto hará que el paquete sea borrado de la faz de nuestro equipo. Así, sin más.

Paquetes útiles y habituales

• nodemon¹⁵- Realmente útil durante el desarrollo ya que relanza la aplicación con cada cambio que hagamos en el archivo, evitando tener que lanzar y detener el proceso contínuamente. • mongoose¹⁶ - Si trabajas con mongoDB¹⁷, este es sin duda uno de los módulos que querras

usar para guardar tus objetos ya que su sintaxis es realmente sencilla y fácil de comprender. • node-mysql¹⁸- Si eres más tradicional y no te apuntas al carro de NoSQL, este conector contra

MySQL funciona realmente bien.

• Nodemailer¹⁹- Si lo que quieres es enviar correos, Nodemailer te lo pone fácil. Este módulo permite SMTP, Amazon SES y la función sendmail que tenga el sistema. En su página

encontrarás ejemplos sobre cómo hacerlo funcionar con Gmail por ejemplo.

• node-validator²⁰ - Validar campos de un formulario es una tarea que, más tarde o más temprano, acabaremos realizando. Este módulo nos ayuda a validar campos y a sanearlos eliminando caracteres blancos, escapándolos, etc.

¿Crees que hay algún paquete que deba estar aquí? ¡Házmelo saber!

Dudas frecuentes

¹⁵https://github.com/remy/nodemon ¹⁶http://mongoosejs.com/ ¹⁷http://www.mongodb.org/ ¹⁸https://github.com/felixge/node-mysql ¹⁹https://github.com/andris9/Nodemailer ²⁰https://github.com/chriso/node-validator

(42)

NPM - Node Packaged Modules 28

..

¿Cómo actualizo un paquete?

Actualizar un paquete es realizar la misma tarea de instalación, es decirnpm install {nombre del paquete}onpm install -g {nombre del paquete}si queremos actualizarlo globalmente. Asegúrate

de revisar las notas de la versión antes de realizarlo, especialmente si es una aplicación en producción, ya que puede que hayan eliminado funciones o cambiado el funcionamiento de algo.

(43)

Cómo mantener Node.js actualizado

Si has leído al principio del libro, ya sabrás que Node.js se actualiza con bastante frecuencia. A veces, incluso un par de veces a la semana.

La pregunta lógica que surge es… ¿cómo mantengo Node.js actualizado?

Ciertamente, podrías seguir los mismos pasos que hemos visto a la hora deinstalar Node.js. Pero, si eres como yo, te parecerá un rollazo. No obstante, hay un método mejor y que yo suelo usar con bastante asiduidad.

El paquete se llamany tendremos que instalarlo de forma global ya que, en el fondo es un programa

de la línea de comandos.

1 $ npm install -g n

Una vez que tenemos instaladonya podemos comenzar a usarlo. Para actualizar la versión de Node.js

solo tendremos que escribir:

1 $ n stable

Y él solo se encargará de hacer el resto. ¿No es genial? A mi personalmente me ahorra bastante tiempo. Estoy suscrito por Twitter a la cuenta deNode.js²¹y, si leo que tienen una actualización solo tengo que lanzar el comando de arriba, esperar un ratillo y disfrutar de una nueva versión.

Lamentablementenno funciona con Windows. Más lamentablemente aun, en su Github no aparece

ninguna incidencia al respecto por lo que parece que no tienen interés en arreglarlo.

ntiene otros comandos que te pueden servir:

Comando Acción

n latest Instala o activa la última versión de node n stable Instala o activa la última versión estable de node n <version> Instala y/o usa la<version>de node especificada n use <version> [args ...] Ejecuta la<version>con[args ...]

n bin <version> Muestra la ruta de los ejecutables de la<version> n rm <version> Elimina la(s) version(es) especificada(s)

n --latest Muestra la última versión disponible de node n --stable Muestra la última versión estable de node n ls Muestra las versiones de node disponibles

(44)

Cómo mantener Node.js actualizado 30 Personalmente he usado a veces n <version>ya que en ocasiones, me han colado como “estable”

una versión y luego resultaba que me habían roto algo que no me dejaba funcionar correctamente.

Sobre las versiones de Node.js

Cuando aparece una nueva versión de Node.js, aparece una noticia en el blog de Node.js o en su Twitter. Concretamente puedes dirigirte al apartado [release] (http://blog.nodejs.org/release/) para ver qué es lo que han sacado.

Cada versión viene con la cadena al lado (Stable) o (Unstable) junto a una escueta explicación de los cambios introducidos. En la mayoría de las ocasiones no nos aportará mucha información ya que suelen ser mejoras de rendimiento y errores corregidos. Pero tendrás que dar un salto de fe. Pensar que lo estable es realmente estable… e instalarlo.

A veces, cuando ocurre un cambio de versión mayor como el que ocurrió al saltar de la versión 0.8 a la 0.10, podemos encontrar unartículo “mucho” más detallado²²e inclusouna página en GitHub²³ donde nos detallan las diferencias entre versiones.

¡Recuerda visitar siempre el blog de Node.js antes de realizar ninguna actualización de versión!

²²http://blog.nodejs.org/2013/03/11/node-v0-10-0-stable/

(45)

Nuestra primera aplicación de

Node.js

Ahora que ya tenemos conocimientos básicos, vamos a ponernos manos a la obra… ¿no? Recuerdo cuando empecé a estudiar programación y todo el mundo le preguntaba a la profesora: ¿cuándo vamos a poder programar? ¿para qué tanta teoría? Así que, no me enrollo más, pongámonos manos a la obra.

Vamos a hacer una sencilla calculadora, nada del otro mundo, pero nos ayudará a ir abriendo boca y a aplicar casi todo lo que hemos visto hasta ahora. Ten en cuenta que este no es el objetivo de Node.js pero no quiero complicar mucho este primer capítulo.

Código de la calculadora

1 var argumentos = process.argv.splice(2),

2 operacion = argumentos[0],

3 valor1 = parseInt(argumentos[1],10),

4 valor2 = parseInt(argumentos[2],10),

5 nombreOperacion, resultado;

6

7 if (operacion === undefined || valor1 === undefined || valor2 === undefined\

8 ) {

9 console.error('Alguno de los parámetros no ha sido especificado.');

10 }

11 else {

12 switch (operacion) {

13 case '*' : {

14 nombreOperacion = 'multiplicación';

15 resultado = valor1 * valor2;

16 break;

17 }

18 case '+' : {

19 nombreOperacion = 'suma';

20 resultado = valor1 + valor2;

21 break;

22 }

23 case '-' : {

24 nombreOperacion = 'resta';

(46)

Nuestra primera aplicación de Node.js 32 26 break; 27 } 28 case '/' : { 29 nombreOperacion = 'división'; 30 if (valor2 !== 0){

31 resultado = valor1 / valor2;

32 }

33 else {

34 console.error('¿Qué querías? ¿¡Cargarte el universo?!')

35 }

36 break;

37 }

38 default : {

39 console.error('La operación %s no ha sido implementada', operacion);

40 break;

41 }

42 }

43

44 if (resultado !== undefined){

45 console.log('El resultado de la %s es %d', nombreOperacion, resultado);

46 }

47 }

Como dijo Jack, vayamos por partes.

En el primer bloque declaramos todas nuestras variables. Es habitual usar las primeras líneas para este cometido. Como ves, nos hacemos con todos los argumentos que le hayamos pasado a la aplicación, como hemos aprendido y declaramos algunas variables vacías que contendrán valores una vez que realicemos la operación en sí.

En caso de no obtener alguno de los tres parámetros que necesitamos (dos valores y la operación) lanzaremos un error para que el usuario sepa que no lo está haciendo correctamente.

Gracias a unswitch, encauzaremos nuestra aplicación por el buen camino. Como puedes ver hemos

implementado 4 operaciones: suma, resta, multiplicación y división. En caso de que no sea ninguna de ellas, devolveremos un error.

Como verás, no hacemos comprobaciones excepto para la división, para evitar divisiones entre cero en cuyo caso, devolvemos un error. Todos somos guardianes del universo. Protegerlo está en manos de todos.

Finalmente, en caso de que tengamos un resultado (!== undefined), mostramos la operación y su

resultado, dando formato a la consola. Hagamos un par de pruebas:

(47)

Nuestra primera aplicación de Node.js 33 1 node app.js '*' 3 4 2 // El resultado de la multiplicación es 12 3 node app.js '+' 997 3 4 // El resultado de la suma es 1000 5 node app.js '^' 2 2

6 //La operación ^ no ha sido implementada ¡Parece que funciona! Nada difícil hasta ahora, ¿no?

Ejercicio

Intenta añadir una nueva operación: la potencia en el que el primer parámetro sea la operación, el segundo el valor a elevar y el tercero la potencia que queremos usar. ¿Hay que hacer alguna validación especial?

(48)

Resumen

Hasta aquí nuestro primer capítulo. Si has seguido hasta aquí el libro, habrás aprendido cuál es la esencia de una aplicación de Node.js y cómo funciona la asincronía. Si no has terminado de entender el concepto, te recomiendo que le vuelvas a echar un vistazo porque es de las cosas más importantes de Node.js y es necesario que el concepto quede claro.

Después, hemos visto cómo hacer uso de la consola de node para imprimir texto y mostrar contenido de los objetos a través de los métodos que nos ofrececonsole. Hemos visto la diferencia entre la

salida normal y la de errores y cómo medir el tiempo con la consola. Sin duda métodos muy útiles para ver qué es lo que va ocurriendo en nuestra aplicación

Adicionalmente, hemos visto cómo podemos valernos de las variables del entorno para poder modificar el comportamiento de nuestra aplicación en función del valor de alguna de las variables. Además, has aprendido a pasar parámetros a tu aplicación de Node.js para ayudar a que tu aplicación funcione.

Además, habrás aprendido a instalar Node.js y npm y cómo interactuar con la consola de Node. npm nos ofrece muchas opciones que no hemos dudado en ver una a una, como instalar o desinstalar paquetes, cómo actualizarlos y la diferencia entre instalaciones globales y locales de paquetes. Finalmente, hemos creado una sencilla calculadora con todo lo que hemos aprendido en este capítulo y nos hemos asegurado de que funciona correctamente.

En el siguiente capítulo, veremos temas más avanzados como exportación/importación de ficheros en nuestra aplicación conrequire, organización de los archivos de nuestra aplicación, emisión de

(49)

Adentrándonos en Node.js

Ahora que ya tenemos los conceptos básicos sobre Node.js, podemos empezar a jugar con conceptos y funciones que son más complejas. Estoy seguro de que es lo que estabas deseando, ¿verdad? A nadie le gustan las presentaciones, son aburridas y odiosas pero, al menos en este caso, estaba totalmente justificada. ¡Lo prometo!

Este capítulo podemos considerarlo como la planta baja de nuestra casa, ya que sobre todos estos fundamentos comenzaremos a profundizar en la tercera parte cuando nos metamos en faena con Express.

(50)

Gestión de dependencias con

package.json

Node.js implementa CommonJS para distribuir paquetes lo cual ayuda a que todo este proceso esté bastante extendido. Esto hace que, si creas una aplicación, la puedas distribuir fácilmente a través denpmpara que pueda ser instalada por cualquiera.

Pero hay una cosa que tienes que tener en cuenta. Tu aplicación puede depender por ejemplo de Express, pero Express a su vez, tiene una serie de dependencias que necesita para funcionar, que a su vez… ¡pueden necesitar más dependencias!

No obstante, queremos evitar a toda costa el tener que bajarnos las dependencias manualmente y, lo que es aun peor, sus versiones. Es por ello, que a la hora de distribuir un paquete a través denpm,

viene sin la carpetanode_modulesen la cual se instalan todas las dependencias.

Es probable que te estés preguntando…

Si Express usa como dependencia aconnect, ¿puedo hacer yorequire('connect')y

usarlo yo también?

Realmente no. Tampoco es buena idea. La gestión de dependencias en cadena que usa Node.js (y la mayoría de los lenguajes), está pensada así para que las versiones no den conflictos entre si. Voy a intentar explicarlo con un ejemplo más gráfico.

Imagina por un momento, que eres carpintero. La programación es muy complicada y has decidido buscar fortuna con otra profesión. Te has bajado de Google un diseño de rueda de carruaje espectacular así que, diseñas tu carruaje alrededor de ese diseño de rueda, para que encaje perfectamente. Hasta ahora todo bien.

Pero decides llevar tu carruaje a una feria para mostrarlo a posibles compradores. En el camino, se te rompe una rueda del carruaje. Un compañero que pasa cerca, se ofrece a prestarte una de sus ruedas. Desmontas la tuya y… nada. No entra la nueva rueda. Tu carruaje depende de la versión de la rueda que te descargaste de Google. La otra no funciona. Ciertamente podrías hacer algunos ajustes a tu carro y usar la otra rueda, pero no es lo ideal.

Por ello, si realmente quieres, puedes usarconnectde Express usando algo así:

1 require('./node_modules/express/node_modules/connect')

Pero si el día de mañana, Express actualiza su versión deconnectes muy probable que tu aplicación

deje de funcionar correctamente por lo que, lo mejor, es especificar la versión que quieres usar en tus dependencias.

References

Related documents

While only the integer type design variables are addressed using a surrogate-based optimization approach, the idea here is to use the AMIEGO algorithm to limit the expensive

preintervention census, when around 400 women were interviewed per cluster, and the estimates that per cluster around 80 children would have been born from around 80 pregnancies

Similar to test data obtained under pure mode I and pure mode II loading conditions at intermediate temperature, the trend of mixed mode I/II fracture energy change is increasing

This section develops a new hybrid learning based adaptive controller using the acceleration feedback to achieve a global position tracking for a n-rigid link

II HIS Honorius edition of is an amalgamation of sev- The Great Grimoire of Pope eral elements; the main text of the book is an English translation of the German

Chairman Carl Whitehead Member Peter Fanelli Member Nicole Gemmati Member Bob Nasser Member Ben Paganelli Member Joan Quinn Member Rocco Romeo.. Alternate Member Ahmad Katnani

(3) We were motivated by the method in the work of [14], which applied fractional calculus for image splicing detection and proposed a new fractional texture descriptor on the

If this becomes the case, in order to meet the learning outcomes of this course, we will do the following; we will meet weekly at the normal class scheduled time via Zoom