Descubriendo Nodejs Express

download Descubriendo Nodejs Express

of 172

Transcript of Descubriendo Nodejs Express

  • Descubriendo Node.js y ExpressAprende a desarrollar en Node.js y descubre cmoaprovechar Express

    Antonio LagunaEste libro est a la venta en http://leanpub.com/descubriendo-nodejs-express

    Esta versin se public en 2013-07-02

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

    2013 Antonio Laguna

  • Twitea sobre el libro!Por favor ayuda a Antonio Laguna hablando sobre el libro en Twitter!El tweet sugerido para este libro es:Acabo de hacerme con Descubriendo Node.js y Express! #descubriendoNodejsEl hashtag sugerido para este libro es #descubriendoNodejs.Descubre lo que otra gente est diciendo sobre el libro haciendo click en este enlace para buscar elhashtag en Twitter:https://twitter.com/search/#descubriendoNodejs

  • Tambin por Antonio LagunaLaravel: Code Happy (ES)

  • ndice general

    Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iDedicado a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iErrare humanum est . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iFeedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iLibro en desarrollo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ii

    Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iiiEvolucin de Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vAlgunas presunciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vAudiencia del libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi

    Introduccin a Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Node.js basado en eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2La asincrona por naturaleza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Instalando Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

    Instalando en Windows y Mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Instalando en Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Funciona mejor Node.js en algn sistema? . . . . . . . . . . . . . . . . . . . . . . . . . . 7Qu acabamos de instalar? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Accediendo a la consola . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

    Hola mundo! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Hola mundo en un servidor! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

    La consola de Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15console.log y console.info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15console.error y console.warn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17console.time y console.timeEnd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

    Accediendo a las variables del entorno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19Pasando parmetros a Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

  • NDICE GENERAL

    NPM - Node Packaged Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Bsqueda de paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Obtener informacin de paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24Lista de paquetes instalados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24Instalacin de paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25Desinstalacin de paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27Paquetes tiles y habituales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27Dudas frecuentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

    Cmo mantener Node.js actualizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29Sobre las versiones de Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

    Nuestra primera aplicacin de Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

    Adentrndonos en Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35Gestin de dependencias con package.json . . . . . . . . . . . . . . . . . . . . . . . . . . 36

    Versionado semntico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37Estructura del archivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

    Exportando en Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Exportando con el objeto exports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Exportando con module.exports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43Algunas aclaraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45Pasando parmetros a require . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

    Organizando el cdigo de nuestra aplicacin . . . . . . . . . . . . . . . . . . . . . . . . . 49El archivo de configuracin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

    Emisin de eventos con EventEmitter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53Patrn del observador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53Emitiendo eventos con Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53Pasando parmetros a los eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54Dejando de escuchar eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55Refactorizando el Hola mundo! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55Creando clases que emiten eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56Un ejemplo real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

    Los Streams en Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60Que es un Stream? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60La funcin pipe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61Lectura - Readable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

  • NDICE GENERAL

    Escritura - writable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Lectura y Escritura - Duplex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66Transformacin - Transform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66Pasarela - PassThrough . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

    El sistema de archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68Leyendo ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68Escribiendo en ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69Los Streams y los ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

    Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

    Introduccin a Express . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73Otros frameworks de Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

    Meteor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74Derby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74flatiron . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75TowerJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75Por qu Express? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

    Instalacin de Express . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77Creando la estructura bsica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78Welcome to Express - Bienvenido a Express . . . . . . . . . . . . . . . . . . . . . . . . . . 80Configuracin de la aplicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

    Guardando y obteniendo valores en la aplicacin . . . . . . . . . . . . . . . . . . . . . . . 83Configurando la aplicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

    Rutas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87Parmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90Cadena de bsqueda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

    Middlewares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95app.use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95En lnea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97Mapeado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98En resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98Middlewares ofrecidos por Express . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

    La peticin - request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102req.body . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102req.param(parametro) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

  • NDICE GENERAL

    req.is(tipo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103req.ip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103req.xhr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

    La respuesta - response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104res.status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104res.redirect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104res.send . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105res.jsonp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105res.sendfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106res.download . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106res.render . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

    Plantillas con Jade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108Sintaxis bsica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109Anidando elementos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112Variables en Jade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112Bloques de cdigo auxiliares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

    Pginas de error en Express . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118Gestin de Login con Passport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120Gestionando la subida de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

    Subiendo varios ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

    Apndice A: Ejecuta tu aplicacin Node.js siempre . . . . . . . . . . . . . . . 138Ejecutando Node.js en segundo plano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139Usando forever . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

    Operaciones con los procesos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141Consejo extra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

    Apndice B: Creando un chat con Socket.io . . . . . . . . . . . . . . . . . . . . . 144Qu es Socket.io? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144La aplicacin que vamos a crear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145Instalando las dependencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146El lado servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146El lado del cliente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

  • IntroduccinDedicado aA Laura, mi mujer. Ella me ha apoyado e impulsado a hacer esto posible. Sin ella, estoy seguro deque este libro no habra tenido lugar. Adems, ha tenido a bien el crear la (para mi) maravillosaportada que da presencia al libro.A mi padre. l no solo me ha animado, si no que puso la semilla de la programacin en mi y esegusanillo de pegarte horas delante del monitor, apasionado por la programacin.Por supuesto a Ryan Lienhart Dahl, creador de Node.js que ha hecho que toda esta revolucin seaposible.A David Lpez, por su inestimable ayuda ofreciendo un valiossimo feedback con cada captulo/sec-cin/coma/espacio/trozo de cdigo/etc que he ido publicando. Gracias!A la comunidad, Node.js no sera lo que es de no ser por esa gran cantidad de paquetes y apoyo querecibe por parte de la comunidad.

    Errare humanum estO 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 faltasde ortografa y gramtica. Eso no quita, que se me pueda haber escapado algo y seguramente, asser. Si te encuentras con cualquier error en el libro, tanto de escritura como de cdigo, te agradeceraque me avisaras envindome un correo a [email protected] incluyendo el captulo o fraserelevante.

    FeedbackTienes alguna crtica constructiva? Quieres hacerme algn comentario? Crees que alguna seccinpodra ser mejorada? Me quieres enviar un jamn? Para todo eso, y mucho ms, envame un correoa [email protected].

    mailto:[email protected]:[email protected]

  • Introduccin ii

    Libro en desarrolloPero esto qu es? He comprado un libro que no est terminado?! Me temo que s. Por qu hehecho esto? Pues porque me gustara nutrirme del feedback que vayis pudiendo ofrecerme sobre ellibro conforme se va escribiendo y as poder ofrecer un libro que sea lo ms til posible al lector.Planeo escribir el libro en tres tandas. Tanto en la primera como en la segunda, estar con un precioreducido para incentivar su adquisicin. Ten en cuenta que una vez te hagas con el libro, podrshacerte con todas las actualizaciones que este tenga, incluso me encargar de que te llegue un correoavisndote del hito.Si te has aventurado a hacerte con el libro durante su gestacin, gracias. De verdad. Ponte encontacto conmigo y hazme saber qu te parece. Como agradecimiento te colocar en los crditos!Actualmente esto es lo que est en desarrollo:

    Apndice A - Uso de Socket.io y aplicacin bsica Apndice B - Uso de conexin contra BD Mongo? MySQL? Ambos?

    mailto:[email protected]

  • IntroduccinEsto que lees, son las primeras palabras de mi primer libro, un gran hito! Le he dado bastantesvueltas a esto de la introduccin as que espero que no quede tan mal despus de todo.Quiz te ests preguntando, y quin es este para ensearme Node.js?Quiz no tenga experiencia con los libros, pero llevo bastante tiempo en la red intentando esparcirmi conocimiento y, hasta ahora, no me ha ido mal! Quiz hayas ledo alguno de los tutoriales deprogramacin que escrib en Funcin 13, mi web. O quiz, te hayas cruzado con alguna de mis guasde World of Warcraft en una pgina de cuyo nombre no quiero acordarme. En cualquier caso meapasiona ensear, y me apasiona el desarrollo, principalmente el desarrollo web. Es por ello quete advierto que no encontrars largas explicaciones ni frases rebuscadas, suelo ser bastante directoaunque por ello aparente que no hay tanto contenido.Voy a hablar un poco de mi, puedes saltrtelo si no te interesa lo entenderaAun sigues aqu? Entonces es que quieres leer algo sobre mi. Intentar mantenerlo breve. SoyAntonio Laguna y soy programador web. Original de un pequeo pueblo del Aljarafe sevillano,en Espaa. Desde pequeo tuve la suerte de trastear con los ordenadores. Con mi padre comoprogramador desde que la informtica se inici, he tenido siempre a mano algn ordenador.Recientemente me he mudado a Londres que, como espero que sepas, es la capital de Reino Unidopara trabajar en Gamesys. Mi empresa se dedica a realizar pginas de juegos de casino: ruleta, cartas,tragaperras, bingo, etc. Tengo la suerte de trabajar con un gran equipo de profesionales de los queestoy aprendiendo da a da. Mi trabajo no es disear las webs, es hacer que stas cobren vida, graciasa JavaScript principalmente.Fue hace unos aos ya que empec a picarme con Node.js. Tena una necesidad que cubrir en mianterior empresa, Accenture y todo lo que lea apuntaba a Node.js. Viniendo de PHP y con algunosconocimientos bsicos sobre JavaScript, me amarr a esa frase del quin dijo miedo? y aquestamos. En mi tiempo libre me encanta leer sobre desarrollo y escribir en mi blog. Pero dejemos dehablar de mi, he venido a hablar de mi libro digo de Node.js.Node.js es una gran revolucin. JavaScript en el lado del servidor? Quin iba a pensarlo? JavaScriptlleva mucho tiempo entre nosotros y ha evolucionado muchsimo como lenguaje y, por suerte, siguehacindolo.

    Vale pero, qu es Node.js?

    Node.js es un sistema del lado del servidor, para escribir cdigo que nos permite crear aplicacionesweb e incluso servidores web que responden a peticiones. Est creado sobre el motor JavaScript quelleva Chrome (V8), lo cual lo hace realmente rpido.

    http://www.funcion13.com

  • Introduccin iv

    Segn la pgina de Node.js, esta es la definicin:

    Node.js es una plataforma creada sobre el motor JavaScript de Chrome para crearaplicaciones de red rpidas y escalables. Node.js utiliza un modelo basado en eventosy entrada/salida que no bloquea, lo cual lo hace ligero y eficiente, perfecto paraaplicaciones que usen muchos datos en tiempo real que puedan ejecutarse de formadistribuida en varios dispositivos.

    Prometedor no? Adems, puede que te interese saber que compaas como Microsoft, Linkedin oYahoo ya estn usando Node.js para el software.

    Un servidor?

    S, has ledo bien. Node.js es capaz de crear un servidor web y no tendrs la necesidad de usar algocomo Apache, lighthttpd o Nginx.

    Pufff qu complicado!

    No! No lo es! Y eso es lo que pretendo demostrarte en este libro. Todas las personas que conozco quehan comenzado con Node.js, han acabado disfrutando mucho del entorno porque tienes muchsimalibertad a la hora de escribir cdigo y sientes que todo est en tus manos.Para que te hagas una idea, crear un servidor ocupa tan solo seis lneas de cdigo como mucho!

    1 var http = require('http');23 var server = http.createServer(function (request, response) {4 response.writeHead(200, {"Content-Type": "text/plain"});5 response.end("Hola Mundo!\n");6 }).listen(8080);78 console.log('Servidor escuchando por el puerto 8080');

    Tampoco quiero agobiarte ahora al principio, pero creo que es un cdigo bastante sencillo deentender.Una de las mejores cosas que tiene Node.js son las libreras que puedes instalar y usar en tus propiosdesarrollos. He aqu un breve listado:

    http://httpd.apache.org/http://www.lighttpd.net/http://nginx.org/en/

  • Introduccin v

    Forever - Te permite ejecutar una aplicacin Node.js para siempre, en caso de que algn erroracabe con ella, forever se encargar de levantarla nuevamente.

    Express - La veremos en este libro pero nos permite crear un servidor web y hacer virguerascon l como responder a distintos verbos HTTP, ejecutar cdigo antes y/o despus de cadaruta, etc.

    Socket.io - Comunicacin en tiempo real con el navegador a travs de WebSockets si estndisponible, o algunas soluciones menos rpidas en caso de ser otro navegador (InternetExplorer).

    Jade - Un sistema de plantillas usado por Express que nos evita tener que escribir muchocdigo para crear HTML.

    Evolucin de Node.jsNode.js ha ido cambiando muchsimo desde que apareci al pblico general. Poco a poco ha idorevolucionando la tecnologa y ms y ms empresas se animan a usar Node. Lo bueno, es que graciasa su versatilidad, puede que ests 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 estn unpoco ms calmados, al principio particularmente los cambios eran contnuos y la estabilidad algodudosa. Pero eso ha cambiado! Dado el gran apoyo de muchas empresas y el inters general queexiste por Node, cada vez es ms estable y robusto y los cambios no suelen ser tan drsticos.Suelen sacar versiones bastante a menudo con la intencin de solucionar errores y, especialmente,mejorar el rendimiento. No obstante, a veces, el cambio de versin es bastante significativo e implicaque ciertas funciones dejen de funcionar como lo hacan antes. Por eso es muy importante revisarla wiki o el blog antes de actualizar.Habitualmente, Node.js mantiene dos versiones. Una inestable, que est en continuo desarrolloy no est recomendada para el uso en produccin, y otra estable que es la que normalmentedescargaremos para nuestras aplicaciones. Aunque ahora mismo no tienes que preocuparte de nadade esto ya que, por regla general, te bastar con la versin estable.

    Algunas presuncionesEn este libro utilizaremos ejemplos basados en sistemas Unix. Esto no implica que no vayan afuncionar en un entorno Windows, si no que vers comandos como ls que no funcionarn enWindows. Aunque no es algo que ocurrir muy a menudo e intento minimizarlo lo mximo posible,tenlo en cuenta si ests siguiendo el libro en Windows.

    https://github.com/joyent/node/wikihttp://blog.nodejs.org/

  • Introduccin vi

    Audiencia del libroEste libro est pensado para lectores que tengan algo de experiencia con algn lenguaje deorientacin a objetos: Ruby, Python, PHP o Java incluso; algo de experiencia con JavaScript y, porsupuesto nuevos con Node.js!En este libro no vamos a explicar los tipos de variables, cmo funciona un bucle for o qu valoresse evalan como false en JavaScript. Lamento decirte que, sin estos conocimientos, quiz te sientasalgo perdido.No obstante, no pretendo que seas un ninja de JavaScript, ni un gur, ni turur. Es ms, en las cosasespecialmente oscuras de JavaScript me detendr si lo veo necesario para ayudarte en el camino delaprendizaje de Node.js y, porqu no, de JavaScript.Puede que te ests 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 tendrs un objeto windowni dispondrs del mtodo alert(), a su vez, el navegador no tiene acceso a funciones de ficheroso a los Streams por ejemplo (sean lo que sean). No obstante, la sintaxis y las palabras claves sonexactamente las mismas con la salvedad de que Node.js usa versiones ms modernas de JavaScriptque solo estn disponibles en los ltimos navegadores.Observa que el ttulo del libro indica claramente Descubre. Este no es un libro para convertirte enMaestro, ni en Ninja ni nada por el estilo. Es para ayudarte en el camino del conocimiento. Por lared esparcida hay mucho conocimiento sobre Node.js pero no todo est actualizado y casi todo estdesperdigado en diferentes sitios. Mi intencin es que comiences conmigo el aprendizaje. Te dar lasherramientas y los conocimientos para comenzar a crear tus propias aplicaciones (sean o no web).Bueno Ests preparado para sumergirte en el mundo de Node.js? Pues adelante, sigue leyendo!Nos vemos en el primer captulo!

  • Introduccin a Node.js

    En la introduccin de el libro ya hemos hablado un poco de Node.js y hasta hemos puesto unsencillo ejemplo! pero no quiero dejar de profundizar un poco ms.Si eres el tipo de lector al que va dirigido este libro, probablemente no tengas mucha experienciacon JavaScript. Tocas aqu un poco, un poco de jQuery por all, este mdulo de pop-ups por ac yun slideshow por all. Qu hay en comn 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 unelemento de la pgina, no es con eso con lo que te vas a encontrar aqu.Node.js es JavaScript del lado del servidor. Realmente es algo ms 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 seams sencillo compararlo con un entorno PHP, Ruby o Python (todos amigos por igual).Para trabajar con Node.js, nos valdremos de la lnea de comandos en muchas ocasiones ya que, enel fondo, no es ms que una interfaz de lnea de comandos. Te vas a sentir todo un hacker! S quemuchas personas le tienen miedo a la lnea de comandos, pero como dice Bane

    1 Yo nac en la lnea de comandos, moldeado por ella. No vi Windows hasta que\2 ya era un hombre...

    Creme cuando te digo que no tienes por qu preocuparte, ya que no vamos a usar ningn comandoraro en ningn caso. Confiars 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 parchs. Si no de operaciones que bloquean (o no) elservidor. Vamos a meternos un poco ms en faena.

  • Node.js basado en eventosLa aplicacin habitual de Node.js, se queda residiendo enmemoria y espera algo por parte del sistemapara ejecutar una funcin. Esto puede ser alguien entrando en una pgina web, un cambio en unfichero de un directorio o un mensaje que llegue por un socket. Piensa en ello como una gasolinera24 horas. Est ah abierta y puede pasar horas sin que nadie vaya, pero eventualmente alguien pasara 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 esnecesario 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 mayora de los lenguajes. Son como eso que imaginassolo que no son personas. Es un proceso que se encarga de revisar el cdigo que est en ejecucin ydecir

    1 A ver, esta variable sigue existiendo? No, no? Pues la quitamos de la mem\2 oria3 Y esta funcin 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 quedaramos sin memoria y eso sera una catstrofe. Todo empezara a ir lento. No solo laaplicacin! Si no el sistema!

    Y puedo yo llamar al recolector de basura?

    No, no puedes ni debes. Si seguimos buenas prcticas de programacin no tendramos nunca quepreocuparnos por este proceso invisible.

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

    Seguro que ests pensando en eso. Mucha gente lo piensa, especialmente los Javasaurios. Y tienesrazn. Node.js no es la panacea y no har todo el trabajo por ti. Es una herramienta que, en manosinexpertas puede parecer poca cosa. En este libro vamos a intentar aprovechar todo ese potencialque 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 tesituranunca de decir, ojal pudiera hacer cosas en paralelo? Pues en Node.js eso es lo que ocurre. Bueno,ms o menos. Vas a tener que confiar en mi, un pequeo salto de f. Si lo hiciste con Altair, seguroque puedes lograrlo!

  • La asincrona por naturalezaEn Node.js hay dos formas de hacer las cosas. Asncronas o sncronas.

    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 sncrono, meteras la tostada. Cuando saliera del tostador,comenzaras a hacer el caf. Cuando el caf saliera de la cafetera, untaras la tostada de mantequilla.Cuando terminaras calentaras algo de leche. Finalmente te podras tomar el desayuno solo que,probablemente, el caf que te eches en la taza est un poco fro y la tostada est fra al untarle lamantequilla.En un mundo asncrono la cosa cambia. Pones la cafetera y, mientras se est haciendo elcaf, calientas la leche y pones la tostada a tostarse. Para cuando termines de hacer la tostadaprobablemente ya tengas el caf preparado y est todo listo para tomarse.Vemoslo ahora con un ejemplo de cdigo:

    Ejemplo 1: Cdigo tradicional sncrono1 var resultado = db.query("SELECT * FROM usuarios");2 // Esperamos a los resultados3 hacerAlgoConEllos(resultado); // Esperamos a que termine4 hacemosOtraCosa();

    Ejemplo 2: Cdigo asncrono1 db.query("SELECT * FROM usuarios", function(resultados){2 hacerAlgoConEllos(resultado); // Esperamos a que termine3 });4 // Esta funcin se ejecuta justo despus de que se haya lanzado la consulta5 // antes de obtener los resultados6 hacemosOtraCosa();

    Y realmente se ejecutan las cosas a la vez?

    La respuesta es no.

  • La asincrona por naturaleza 4

    Aqu est el engao

    Te dije que confiaras en mi. En apariencia se ejecutan a la vez. Sin embargo, tras el teln, lo querealmente pasa es que las callbacks quedan en una pila y se van ejecutando. Hasta que ese callbacktermine, el resto tendr que esperar. Lo que ocurre, es que el motor de Node.js es tan rpido ynormalmente 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 gustanlas explicaciones tcnicas, lo que realmente ocurre es que JavaScript, tanto el cliente como en elservidor, se ejecuta en un nico hilo, por lo que es tcnicamente imposible que haga dos cosas a lavez. Pero confa en mi, esto no es ningn problema.Esto puede resultar un poco confuso, especialmente al principio. Pero si me vas siguiendo no deberasperderte en el camino de la asincrona.

  • Instalando Node.jsPara no aturdirte en demasa, vamos con algo ahora sencillito. As vamos intercalando una de caly otra de arena. Vamos a ponernos manos a la obra y a instalar Node.js para poder empezar acacharrear que es lo que a todos nos gusta, verdad? Como vers es un proceso realmente sencillo.

    Instalando en Windows y MacEl proceso de instalacin en ambos sistemas es exactamente el mismo.

    1. Nos dirijimos a la pgina de Node.js: http://nodejs.org/2. Le damos al botn grande y verde que pone INSTALL. Esperamos.3. Una vez finalice la descarga, tendremos un archivo .msi o .pkg depende del sistema en el que

    estemos. Lo localizamos y hacemos doble click.4. Finalmente, seguimos el proceso de instalacin que es bastante sencillo.5. Profit.

  • Instalando Node.js 6

    Figura 1: Instalacin de Node.js en Mac OSX

    Instalando en LinuxCubrir cada distribucin de Linux es una locura, pero el proceso no debera variar mucho. En estecaso, vamos a ver cmo instalar Node.js en Ubuntu.

    1. Nos dirijimos a la pgina de Node.js: http://nodejs.org/2. Le damos al botn de DOWNLOAD.3. En la siguiente pgina, tendremos que elegir el cdigo 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, deberamos colocarlo en la carpeta /usr/local/src.5. Ahora hacemos algo como esto:

  • Instalando Node.js 7

    Descomprimiendo e instalando Node.js

    1 tar -zxf node-v0.10.5.tar.gz2 cd node-v0.10.53 ./configure4 make5 sudo make install

    Atencin

    Puede que necesites realizar sudo para realizar algunas acciones. Ten en cuenta adems,que el proceso puede llevar algo de tiempo. Si necesitas ms informacin para instalarNode.js en alguna versin de Linux en partcular, revisa las instrucciones de instalacinen la wiki de Node.js.

    Funciona mejor Node.js en algn 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 peazo, por no decir una palabra ms fea. Habaque usar compiladores y armarse de paciencia.Por suerte, Microsoft entendi que no se poda quedar atrs en esto, y se ali con Joyent (la empresadetrs de Node.js) para portar Node.js a Windows como Dios manda.Aun as, hay algunos paquetes que no funcionan enWindows porque tienen dependencias especialesde Unix. Esto no quiere decir que no vayas a poder trabajar Para nada! De hecho, los ejemplosque encuentres aqu los pruebo siempre en ambos sistemas por lo que no deberas preocuparte paranada.

    Qu acabamos de instalar?Seguramente pienses que me he vuelto loco

    No estabamos instalando Node.js? Por qu me haces esa pregunta?https://github.com/joyent/node/wiki/Installation

  • Instalando Node.js 8

    La verdad es que s, que estbamos instalando Node.js. Lo que no te he contado es que adems,acabamos de instalar npm. Esto ocurre de forma automtica desde la versin 0.6.3 y es totalmentetransparente.Ahora mismo no quiero que te preocupes demasiado sobre lo que es npm. No te distraigas! Sigamosla senda del conocimiento OhmmmVamos a comprobar qu tenemos. Abre el terminal y escribe lo siguiente:

    1 node --version

    Si todo fue bien, debers ver algo como:

    1 v0.10.11

    Bien! Ahora podemos seguir.

    Accediendo a la consolaTanto enMac como Linux, la consola no es ms que el terminal del sistema y suele llamarse Terminala secas. Especialmente en Linux estars acostumbrado a usarla de cuando en cuando, pues muchosprogramas y/o paquetes necesitan del uso eventual de la consola.No obstante, en Windows es una versin modificada del cmd que nos crea directamente Node.js alinstalarla. Esta versin no tiene nada de especial, solo que nos aade algunas variables de entorno ynos inicia automticamente como administradores, de esta manera podremos ejecutar Node.js conmenos fricciones. Seguro que, con paciencia y saliva puedes hacer funcionar la consola normal deWindows como lo hace la de Node.js. nimo e intntalo!Para acceder a ella no tienes ms que ir a la carpeta que el proceso de instalacin habr creado enel men de inicio:

    Figura 2: Consola de Node.js en Windows

  • Hola mundo!Antes de pasar a explicar nada ms, y solo por seguir con la costumbre, vamos a crear nuestroprimer programa de Node.js y para ello vamos a ver dos formas de hacerlo. Si no te suena paranada esta prctica, debera! Lo que intentamos hacer es, que usando el lenguaje sobre el que estamosaprendiendo, mostremos algo as como un saludo. Normalmente es Hola Mundo! o Hello World! enIngls.Primero escribe node en la consola.Ya? Si todo ha ido bien, debera quedarse con un smbolo > esperando nuestras rdenes. No pdoemosdarle 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? Ququieres 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 cmo lo explico.undefined es solo que la sentencia que acabamos de escribir, no devuelve ningn valor. Aunqueseguro que ya lo sabes, ehem, el valor undefined es como si no hubiera valor alguno. Si alguna vezhas usado la consola de las herramientas de desarrollador de Chrome, vers que el comportamientoes exactamente el mismo.Vamos a ver qu pasa si ponemos algo que s devuelva un valor.

    1 parseInt('30',10);

    Aunque esto tambin seguro que lo sabes, parseInt intenta transformar una cadena en un nmeroy lo devuelve as que, en esta ocasin, veremos que nada ms darle al Enter nos devuelve un 30.Ahora que ya hemos probado esto rpidamente, veamos el otro mtodo.

  • Hola mundo! 10

    Pero cmo salgo de aqu?!

    Upss casi me olvido. Para salir, pulsa Ctrl + C (dos veces) y se cerrar la consola de Node. Esta esla forma de terminar un proceso.El otro metodo, como pronto descubrirs, es como lo haremos habitualmente, colocando el cdigoen un archivo. No creeras 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 aplicacin.

    1 $ mkdir holamundo2 $ cd holamundo/

    Ahora que ya estamos dentro de la carpeta, y si ests en un sistema Unix, puedes hacer lo siguientepara 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 nombrede app.js es solo una convencin para indicar que es el archivo que contiene la aplicacin y, portanto, el ejecutable.Ahora abre el archivo con tu editor de texto preferido (si es que no lo habas hecho ya) y escribedentro lo siguiente:

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

    Gurdalo, y en el terminal escribe:

    1 $ node app.js

    Esta vez deberamos ver el mensaje sin el undefined de antes y, tras aparecer, la aplicacin se cerrarsin ms. Fcil! no?

    Hola mundo en un servidor!Recuerdas el ejemplo que pusimos en la introduccin del libro? Vamos a revivirlo. Vamos a crearvida! Quita todo el cdigo de app.js y escribe lo siguiente:

  • Hola mundo! 11

    Hola mundo en el servidor1 var http = require('http');23 var server = http.createServer(function (request, response) {4 response.writeHead(200, {"Content-Type": "text/plain"});5 response.end("Hola Mundo!\n");6 }).listen(8080);78 console.log('Servidor escuchando por el puerto 8080');

    Si ahora lo ejecutas con

    1 $ node app.js

    Vers que en la consola aparece el mensaje Servidor escuchando por el puerto 8080 que hemospuesto en la lnea 8. Ahora accede a http://localhost:8080 y, si todo ha ido bien, deberas ver unapgina que dice Hola Mundo!.Veamos el ejemplo lnea a lnea:En la primera lnea lo que hacemos es require. Quiz puedas deducir lo que hace porque tenemosun verbo bastante similar en castellano. Esta sentencia es la forma que tiene Node.js de cargarlos mdulos. Es similar a include de PHP, #include de C o import en Python. Quiz te estspreguntando porqu difiere de include si tanto PHP como C usan include. El motivo es que requirees una sentencia comn cuando usamos require.js en el navegador para modularizar aplicacionesJavaScript. Tampoco quiero profundizar mucho en esto porque puede ser un poco complejo.En este caso, lo que estamos requiriendo es el mdulo http que, casualmente, es un paquete delncleo 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 mdulos del mismo modoque se llama el mdulo, recuerda que es solo una convencin para mantener la cordura.Siempre puedes poner var ptth = require('http'); si quieres volver loca a la genteque lea tu cdigo.

    Lo siguiente que hacemos es crear un servidor valindonos de la funcin createServer que nosfacilita http. sta recibe como parmetro una funcin, en este caso annima, con dos parmetros

  • Hola mundo! 12

    request, que es la peticin, y response que es la respuesta que tenemos que enviar. Esa funcin serllamada cada vez que alguien entre en la URL de nuestro servidor, as que tenemos que decirle loque tiene que hacer.En nuestro caso, le indicamos que la peticin debe tener un cdigo 200, que es el cdigo HTTP paradecir que la peticin es correcta, y que el tipo de contenido que tiene que esperar el navegador estexto plano. Adems, finalizamos la respuesta con el mtodo end, aadiendo el texto que queremosdevolver.

    Qu pasara si no llamramos a end?Si no llamramos al mtodo end de la respuesta, la peticin nunca terminar y elnavegador acabar por dar un error porque sigue esperando que le enviemos datos. Nome crees? Prubalo y vers!

    Antes dije: en este caso annima. Ten en cuenta que este cdigo sera totalmente equivalente yvlido:

    Funcin no annima

    1 var http = require('http');23 function gestionaPeticion (request, response) {4 response.writeHead(200, {"Content-Type": "text/plain"});5 response.end("Hola Mundo!\n");6 }78 var server = http.createServer(gestionaPeticion).listen(8080);910 console.log('Servidor escuchando por el puerto 8080');

    O incluso este:

  • Hola mundo! 13

    Funcin en variable

    1 var http = require('http');23 var gestionaPeticion = function (request, response) {4 response.writeHead(200, {"Content-Type": "text/plain"});5 response.end("Hola Mundo!\n");6 }78 var server = http.createServer(gestionaPeticion).listen(8080);910 console.log('Servidor escuchando por el puerto 8080');

    La funcin createServer recibe otra como parmetro y se encargar de ejecutarla cuando hayaterminado su trabajo. Esto se conoce como callback. Es un patrn muy comn cuando se hacencosas asncronas ya que, sabemos cundo se comienza a ejecutar el cdigo, pero no sabemos cundova a acabar.En Node.js, los callbacks por norma general tienen la siguiente estructura. El primer parmetro deun callback debe ser un error si lo hubiere, en caso contrario null. A continuacin, le siguen el restode parmetros.

    Espera Antonio, entonces Node.js no est siguiendo su propio patrn?

    No es eso. Lo que realmente ocurre es que la funcin que estamos pasando ms que un callback esalgo que est a la escucha para cuando llega una peticin al servidor. El servidor tiene sus propioscallbacks internos a la hora de realizar tareas asncronas y, si hay un error, se encargar de gestionarlol por lo que nuestra peticin debera llegar sin ms.En la siguiente lnea, le decimos por el puerto por el que escuchar, en este caso el 8080. Puedes elegircualquier otro puerto que no est en uso. Quin soy yo para decirte que no uses el puerto 6969 paratu desarrollo? Nadie!Como vers, la llamada est encadenada con createServer. Eso es lomismo que poner justo debajo

    1 server.listen('8080');

    puesto que createServer lo que devuelve es un objeto servidor.

  • Hola mundo! 14

    Te has fijado?

    Si eres observador habrs visto que detrs de createServer tenemos una llamada a lafuncin listen. Esto se conoce como encadenamiento de funciones y se logra devol-viendo siempre el objeto creado, en este caso el servidor. Este tipo de comportamientose ha hizo especialmente comn cuando apareci jQuery.

  • La consola de NodeSi habis estado atentos, habris visto que hemos estado usando console.log y que, la informacinque hemos puesto, apareca en el terminal mientras ejecutbamos la aplicacin.Si has trabajado con JavaScript (cosa que espero) quiz ya ests acostumbrado a console puesto quees una forma de mostrar en la consola del Navegador informacin para ver por dnde va pasandonuestro cdigo.console sirve para escribir en la salida estndar y en la de error. sta nos ayudar enormemente en latarea de saber qu es lo que est pasando en las entraas de nuestra aplicacin sin ser excesivamentecomplicado como podra ser el hecho de activar un depurador.Aunque no es algo de lo que, a priori, tengamos que preocuparnos, cabe destacar que escribir enla consola es un mtodo sncrono por lo que, si abusamos brutalmente de ella, estaremos creandobloqueos en nuestra aplicacin.Hay libreras estupendas para registro de eventos y logging en general para Node, como winston.No obstante, para el propsito de este libro nos valdremos de las bondades de la consola ya que cubretodas las necesidades de aprendizaje.

    console.log y console.infoEstas dos funciones hacen exactamente lo mismo, pasar informacin a la salida por defecto. Laprimera 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 nospermite formatear la informacin al ms puro estilo sprintf de PHP.Imagina que quieres mostrar el nmero de planetas que hay en nuestro sistema solar, pero en vezde poner un nmero ah en plan soso, con una frase para dotarlo de sentido. Podras hacer esto:

    1 var planetas = 8;23 console.log('Hay ' + planetas + ' planetas'); // Hay 8 planetas

    Ya que lo que estamos pasando es, de hecho, una cadena de caracteres. No obstante, no sera mejortener que evitarnos todos esos +? Yo creo que s. Vamos a ver cmo lograrlo.

    https://github.com/flatiron/winston

  • La consola de Node 16

    1 var planetas = 8;23 console.log('Hay %d planetas', planetas); // Hay 8 planetas

    Lo que hacemos es pasarle a la consola una cadena, y parmetros extra que sustituir en ordende aparicin. Ten en cuenta que si pasas ms parmetros de los que realmente pones, Node.jssmplemente lo pondr al final.

    1 var planetas = 8,2 expulsado = "Plutn";34 console.log('Hay %d planetas',planetas,expulsado); // Hay 8 planetas Plutn

    Vamos a arreglarlo, pasando un parmetro ms:

    1 var planetas = 8,2 expulsado = "Plutn";34 console.log('Hay %d planetas porque %s ya no es uno de ellos',planetas,expu\5 lsado);6 // Hay 8 planetas porque Plutn ya no es uno de ellos

    Como ves, ahora hemos puesto la cadena en su sitio.

    Vale, pero qu es eso de %d y %s?

    Me alegra que lo preguntes oh espera! Esos valores son patrones que podemos usar para sustituircadenas. Hay ms!

    Patrn Tipo%d Enteros y coma flotante%s Cadenas%j Objetos JSON

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

  • La consola de Node 17

    1 var sistema_solar = {2 planetas : 8,3 expulsarPluton : function() {4 ...5 }6 };78 console.log(sistema_solar);9 //{ planetas: 8, expulsarPluton: [Function] }

    Como ves, intenta convertirlo a JSON y mostrarnos tanto sus propiedades como mtodos para quepodamos evaluar, a simple vista, el valor del objeto.

    console.error y console.warnEstas funciones son equivalentes y hacen lo mismo que log e info salvo que en vez de a la salidapor defecto, lo envan a la de errores.

    Qu es eso de la salida de errores?

    La salida de errores es una salida alternativa. Esto permite ms flexibilidad puesto que puedes tenerdos tipos de logs. Uno para errores (que sern importantes) y otro de informacin (ms trivial). Estoes especialmente til cuando tienes multitud de mensajes mostrndose por tu aplicacin y t soloquieres centrarte en los problemticos.

    console.time y console.timeEndEstas funciones las usaremos para hacer pruebas de rendimiento de nuestro cdigo. La primerafuncin es como si agarrramos un cronmetro, lo pusiramos a 0 y empezramos a contar.

    1 console.time('Operacin costosa');2 // Aqu realizamos una operacin costosa3 console.timeEnd('Operacin costosa');

    timeEnd es como si parramos ese cronmetro, mirramos el tiempo y lo anunciramos al mundo.Cuando se ejecute, veremos aparecer algo como:

  • La consola de Node 18

    1 Operacin costosa: 33ms

    Esta es una forma realmente conveniente de saber dnde podemos tener algn cuello de botella ennuestro cdigo.

  • Accediendo a las variables delentornoQuiz ni siquiera sepas lo que es una variable de entorno. No te avergences. Es una cosa que hoyen da ya casi no se aprender ya que no son tan necesarias como antiguamente. No obstante, ensistemas 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 yque 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 cmo acta ens el sistema.Una de las variables ms conocidas es el PATH, 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,podrs ejecutar una aplicacin sin necesidad de ir a donde est ubicado.Definir una variable de entorno es realmente sencillo:

    1 // Unix2 NUESTRA_VARIABLE="Su valor"; EXPORT NUESTRA_VARIABLE3 // Windows4 set NUESTRA_VARIABLE="Su valor"

    En sistemas Unix tenemos adems la oportunidad de crear una variable que solo ser visible dentrode Node.js, en esa ocasin que la lancemos.Lo ms habitual es establecer la variable NODE_ENV, que establece el tipo de entorno en el que estamostrabajando que normalmente ser production (produccin) o development (desarrollo):

    1 NODE_ENV=production node app.js

    Todas las variables del entorno estn accesibles desde el objeto env, que forma parte del objetoprocess. De esta manera, si queremos por ejemplo cambiar el puerto en el que vamos a ejecutarnuestra aplicacin, en funcin del entorno en el que estemos, haramos algo as:

  • Accediendo a las variables del entorno 20

    1 var puerto = 80;23 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 alcerrar la aplicacin, o bien al reiniciar el equipo. Si quieres aadir las variables de formapermanente, tendrs que valerte de/.bash_profile en sistemas Unix o cambiarlas enlas propiedades del sistema en un entorno Windows.

  • Pasando parmetros a Node.jsAdems de valernos de las variables del entorno, podemos pasarles parmetros a Node.js de lasiguiente forma:

    1 $ node app.js [argumentos]

    Este tipo de tcnicas es especialmente til si, en vez de crear un servidor, creamos algn tipo deaplicacin que haga un proceso en funcin de uno o varios parmetros. Por ejemplo, imagina unpequeo script que compare dos ficheros de texto y cree un tercero con las diferencias. En esecaso, podras pasar los dos nombres de los ficheros a comparar y, un posible tercer parmetro,que contenga el nombre del archivo diferencial que se genere Esos argumentos van separados porespacios y quedan almacenados dentro del objeto argv, que forma parte de process. No obstante,hay dos valores fijos dentro del objeto:

    1. node2. El nombre del script que estamos ejecutando. Por ejemplo:

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

    En la mayora de las ocasiones, estos argumentos no nos interesan para nada. Por ello, podramoshacer algo as:

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

    Por si no ests familiarizado con splice, lo que hace es en ese caso recortar la matriz y dejar lo quequeda a partir del elemento 2. Dado este cdigo:

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

    Si llamramos a la aplicacin de esta forma: node app.js uno dos tres el resultado sera:

    1 [ 'uno', 'dos', 'tres' ]

  • Pasando parmetros a Node.js 22

    Ya que ha eliminado los dos primeros iniciales, que no nos interesaban.

    De inters

    En caso de que quieras crear un programa de consola, al que le puedas pasar variosparmetros, un buen mdulo que he usado en alguna que otra ocasin con bastantexito es Optimist. Una librera que te permite parsear opciones, aadir alias, parmetrosobligatorios, men de ayuda automtico, etc.

    https://github.com/substack/node-optimist

  • NPM - Node Packaged ModulesComo ya hemos comentado, npm es instalado conNode.js de forma automtica. S, sin que tengamosque hacer nada de particular. Lo bueno es que cuando actualicemos Node.js, npm lo haga tambinde forma automtica.

    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 actuacin con paquetesde node. Buscarlos, instalarlos, actualizarlos, etc. Es posible que hayas utilizado algn gestor depaquetes con anterioridad. Los hay para varios sistemas:

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

    Vamos a ver cmo podemos hacer algunas de estas operaciones con npm. Especialmente las mstiles.

    Bsqueda de paquetesEn ocasiones querremos buscar algo. No sabemos cmo se llama el mdulo pero sabemos quequeremos algo para gestionar uhmm asincrona! Si el programador del paquete lo ha hecho bien,debera 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 ms que escribir npm search {palabra abuscar}. Por ejemplo:

    1 $ npm search async

    Esto comenzar a aparecer por pantalla:{lang=text NAME DESCRIPTIONabiogenesis 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 lospaquetes que contengan esa palabra en su descripcin y/o nombre, por lo que lo mejor es saber de

  • NPM - Node Packaged Modules 24

    antemano qu vamos a usar. Pero, por lo menos, hemos satisfecho nuestro orgullo friki y hemosbuscado paquetes desde la lnea de comandos. Ests hecho un hacker!Aunque no sea tan emocionante, puedes hacer la misma bsqueda en https://npmjs.org/ ya que esdonde npm search busca sus paquetes

    Obtener informacin de paquetesAhora que tenemos una lista de paquetes, seguro que quieres saber algo ms de los paquetes. Yo,que soy muy curioso, tengo ganas de saber qu hace el paquete abiogenesis. No es que lo conozca,lo prometo. Es que es un nombre rarsimo. Para saber los detalles de un paquete, escribiremos npmview {nombre del paquete}.

    1 $ npm view abiogenesis

    Esto realmente nos devuelve una visualizacin del archivo package.json. No te preocupes muchopor l ahora mismo, lo veremos en breve. Ya s que tienes curiosidad, as que te voy a poner unpequeo 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 fantstico framework que ejecuta tareas asncronas y anidadas con resolucin dedependencias! Tendr ziritione?

    Lista de paquetes instaladosEn ocasiones querrs ver la lista de paquetes que tienes instalados en tu aplicacin. Para ello, solotenemos que ejecutar un sencillo comando:

    1 $ npm ls

    Y veremos algo as:

  • NPM - Node Packaged Modules 25

    1 /Users/antonio.laguna/projects/nodetest2 [email protected] [email protected]

    Esta lista nos muestra los paquetes en forma de rbol. Como ves, nos muestra que en mi proyectotengo instalado less, cuya versin es 1.3.3. Abajo, tenemos otro paquete, ycssmin. Este paquete,por el grfico, podemos saber que es una dependencia de less. Esto es, less necesita a nycssmin parafuncionar. Como veremos ahora, cuando instalamos un paquete, npm se trae todas sus dependencias.Ahora tambin hablaremos de los paquetes globales. Basta decir con que si quieres ver una lista detodos los paquetes que tienes instalados a nivel global, solo tienes que hacer algo as:

    1 $ npm ls -g

    Y vers todos los paquetes globales que tienes instalados, con sus dependencias por supuesto.

    Instalacin de paquetesAntes de meternos de lleno a instalar paquetes como cosacos, vamos a hablar sobre el tipo deinstalaciones. Ya las hemos dejado caer un poco en la anterior seccin pero all vamos. Tenemosdos tipos de instalaciones: La instalacin global y la instalacin local.Veamos la diferencia.Los paquetes locales son aquellos que se instalan sobre la aplicacin en la que ests trabajando enel momento en que ejecutas el comando. Si por lo que sea la instalas en una carpeta que no debas,se instalar igualmente puesto que npm no distingue si ests o no en una aplicacin. Los paqueteslocales solo estarn disponibles en el paquete actual. Normalmente es la forma ms habitual deinstalar un paquete.Para instalar un paquete localmente, solo tenemos que ejecutar el siguiente comando npm install{nombre del paquete}. Por ejemplo:

    1 $ npm install less

    Ahora tu proyecto, podr hacer var 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 unprograma de la lnea de comando. En esos casos tendremos que instalarlo de forma global. Hacerloes realmente sencillo ya que nicamente tenemos que aadir un distintivo : npm install -g {nombredel paquete}. Por ejemplo:

  • 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 detodas las aplicaciones usando require().

    Cmo decidir qu tipo de instalacin realizarPiensa que, en general, una instalacin global no es algo bueno. Seguro que, trabajando conJavaScript has ledo que las variables globales son malas. Las instalaciones globales tambin.Bueno, no es que sean malas, solo que es algo que no tendramos que tomar a la ligera.

    Entonces, cmo puedo decidir?

    Veamos unos consejos:

    Si quieres instalar un paquete que funcione dentro de tu aplicacin con require(), instlalode manera local.

    Si ests instalando un paquete que puede ser usado desde la lnea de comandos como unprograma o algn uso extendido (como en el caso de Express), instlalo de manera global.

    Algunos de los paquetes que suelen instalarse de manera global:

    Express forever nodemon Bower Grunt Uglify-js

    Webs de instalacin de paquetesAlgunos usuarios han decidido mejorar las, ehem, bondades de npm search creando algunasherramientas realmente tiles.Una web realmente til a la hora de instalar paquetes es Nipster. Esta herramienta te permitevisualizar un ranking de los paquetes enGithub, permitindote ordenarlos por Fecha deModificacin(til para saber si siguen o no activos), nmero de forks, estrellas, etc.Como alternativa a Nipster, encontramos Gitmoon, que nos ofrece mucha ms informacinde la que podamos encontrar en Nipster sobre cualquier paquete que queramos buscar como ladependencia entre proyectos, quin usa el paquete, etc.Si descubres (o creas!) alguna web que creas que puede cumplir con estas funciones, hzmelo saber!

    http://eirikb.github.io/nipster/http://www.gitmoon.com/

  • NPM - Node Packaged Modules 27

    Desinstalacin de paquetesDesinstalar un paquete es tan sencillo como instalarlo. Durante el desarrollo es normal probarpaquetes, puede que luego no te guste, no cumpla con tus expectativas o, directamente, no lo necesitesy lo hayas instalado porque tena 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 ms.

    Paquetes tiles y habituales nodemon - Realmente til durante el desarrollo ya que relanza la aplicacin con cada cambioque hagamos en el archivo, evitando tener que lanzar y detener el proceso contnuamente.

    mongoose - Si trabajas con mongoDB, este es sin duda uno de los mdulos que querrasusar para guardar tus objetos ya que su sintaxis es realmente sencilla y fcil de comprender.

    node-mysql - Si eres ms tradicional y no te apuntas al carro de NoSQL, este conector contraMySQL funciona realmente bien.

    Nodemailer - Si lo que quieres es enviar correos, Nodemailer te lo pone fcil. Este mdulopermite SMTP, Amazon SES y la funcin sendmail que tenga el sistema. En su pginaencontrars ejemplos sobre cmo hacerlo funcionar con Gmail por ejemplo.

    node-validator - Validar campos de un formulario es una tarea que, ms tarde o mstemprano, acabaremos realizando. Este mdulo nos ayuda a validar campos y a sanearloseliminando caracteres blancos, escapndolos, etc.

    Crees que hay algn paquete que deba estar aqu? Hzmelo saber!

    Dudas frecuentes

    https://github.com/remy/nodemonhttp://mongoosejs.com/http://www.mongodb.org/https://github.com/felixge/node-mysqlhttps://github.com/andris9/Nodemailerhttps://github.com/chriso/node-validator

  • NPM - Node Packaged Modules 28

    ..

    Cmo actualizo un paquete?Actualizar un paquete es realizar la misma tarea de instalacin, es decir npm install {nombre delpaquete} o npm install -g {nombre del paquete} si queremos actualizarlo globalmente. Asegratede revisar las notas de la versin antes de realizarlo, especialmente si es una aplicacin en produccin,ya que puede que hayan eliminado funciones o cambiado el funcionamiento de algo.

  • Cmo mantener Node.js actualizadoSi has ledo al principio del libro, ya sabrs que Node.js se actualiza con bastante frecuencia. A veces,incluso un par de veces a la semana.La pregunta lgica que surge es cmo mantengo Node.js actualizado?Ciertamente, podras seguir los mismos pasos que hemos visto a la hora de instalar Node.js. Pero,si eres como yo, te parecer un rollazo. No obstante, hay un mtodo mejor y que yo suelo usar conbastante asiduidad.El paquete se llama n y tendremos que instalarlo de forma global ya que, en el fondo es un programade la lnea de comandos.

    1 $ npm install -g n

    Una vez que tenemos instalado n ya podemos comenzar a usarlo. Para actualizar la versin deNode.jssolo tendremos que escribir:

    1 $ n stable

    Y l solo se encargar de hacer el resto. No es genial? A mi personalmente me ahorra bastantetiempo. Estoy suscrito por Twitter a la cuenta de Node.js y, si leo que tienen una actualizacin solotengo que lanzar el comando de arriba, esperar un ratillo y disfrutar de una nueva versin.Lamentablemente n no funciona con Windows. Ms lamentablemente aun, en su Github no apareceninguna incidencia al respecto por lo que parece que no tienen inters en arreglarlo.n tiene otros comandos que te pueden servir:

    Comando Accinn latest Instala o activa la ltima versin de noden stable Instala o activa la ltima versin estable de node

    n Instala y/o usa la de node especificadan use [args ...] Ejecuta la con [args ...]n bin Muestra la ruta de los ejecutables de la n rm Elimina la(s) version(es) especificada(s)n --latest Muestra la ltima versin disponible de noden --stable Muestra la ltima versin estable de noden ls Muestra las versiones de node disponibles

    https://twitter.com/nodejs

  • Cmo mantener Node.js actualizado 30

    Personalmente he usado a veces n ya que en ocasiones, me han colado como estableuna versin y luego resultaba que me haban roto algo que no me dejaba funcionar correctamente.

    Sobre las versiones de Node.jsCuando aparece una nueva versin de Node.js, aparece una noticia en el blog de Node.js o en suTwitter. Concretamente puedes dirigirte al apartado [release] (http://blog.nodejs.org/release/) paraver qu es lo que han sacado.Cada versin viene con la cadena al lado (Stable) o (Unstable) junto a una escueta explicacin de loscambios introducidos. En la mayora de las ocasiones no nos aportar mucha informacin ya quesuelen ser mejoras de rendimiento y errores corregidos. Pero tendrs que dar un salto de fe. Pensarque lo estable es realmente estable e instalarlo.A veces, cuando ocurre un cambio de versin mayor como el que ocurri al saltar de la versin 0.8a la 0.10, podemos encontrar un artculo mucho ms detallado e incluso una pgina en GitHubdonde nos detallan las diferencias entre versiones.Recuerda visitar siempre el blog de Node.js antes de realizar ninguna actualizacin de versin!

    http://blog.nodejs.org/2013/03/11/node-v0-10-0-stable/https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10

  • Nuestra primera aplicacin deNode.jsAhora que ya tenemos conocimientos bsicos, vamos a ponernos manos a la obra no? Recuerdocuando empec a estudiar programacin y todo el mundo le preguntaba a la profesora: cundovamos a poder programar? para qu tanta teora? As que, no me enrollo ms, pongmonos manosa la obra.Vamos a hacer una sencilla calculadora, nada del otro mundo, pero nos ayudar a ir abriendo bocay a aplicar casi todo lo que hemos visto hasta ahora. Ten en cuenta que este no es el objetivo deNode.js pero no quiero complicar mucho este primer captulo.

    Cdigo de la calculadora1 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;67 if (operacion === undefined || valor1 === undefined || valor2 === undefined\8 ) {9 console.error('Alguno de los parmetros no ha sido especificado.');10 }11 else {12 switch (operacion) {13 case '*' : {14 nombreOperacion = 'multiplicacin';15 resultado = valor1 * valor2;16 break;17 }18 case '+' : {19 nombreOperacion = 'suma';20 resultado = valor1 + valor2;21 break;22 }23 case '-' : {24 nombreOperacion = 'resta';25 resultado = valor1 - valor2;

  • Nuestra primera aplicacin de Node.js 32

    26 break;27 }28 case '/' : {29 nombreOperacion = 'divisin';30 if (valor2 !== 0){31 resultado = valor1 / valor2;32 }33 else {34 console.error('Qu queras? Cargarte el universo?!')35 }36 break;37 }38 default : {39 console.error('La operacin %s no ha sido implementada', operacion);40 break;41 }42 }4344 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 lneas paraeste cometido. Como ves, nos hacemos con todos los argumentos que le hayamos pasado a laaplicacin, como hemos aprendido y declaramos algunas variables vacas que contendrn valoresuna vez que realicemos la operacin en s.En caso de no obtener alguno de los tres parmetros que necesitamos (dos valores y la operacin)lanzaremos un error para que el usuario sepa que no lo est haciendo correctamente.Gracias a un switch, encauzaremos nuestra aplicacin por el buen camino. Como puedes ver hemosimplementado 4 operaciones: suma, resta, multiplicacin y divisin. En caso de que no sea ningunade ellas, devolveremos un error.Como vers, no hacemos comprobaciones excepto para la divisin, para evitar divisiones entre ceroen cuyo caso, devolvemos un error. Todos somos guardianes del universo. Protegerlo est en manosde todos.Finalmente, en caso de que tengamos un resultado (!== undefined), mostramos la operacin y suresultado, dando formato a la consola.Hagamos un par de pruebas:

  • Nuestra primera aplicacin de Node.js 33

    1 node app.js '*' 3 42 // El resultado de la multiplicacin es 123 node app.js '+' 997 34 // El resultado de la suma es 10005 node app.js '^' 2 26 //La operacin ^ no ha sido implementada

    Parece que funciona! Nada difcil hasta ahora, no?

    Ejercicio

    Intenta aadir una nueva operacin: la potencia en el que el primer parmetro sea laoperacin, el segundo el valor a elevar y el tercero la potencia que queremos usar. Hayque hacer alguna validacin especial?

  • ResumenHasta aqu nuestro primer captulo. Si has seguido hasta aqu el libro, habrs aprendido cul es laesencia de una aplicacin de Node.js y cmo funciona la asincrona. Si no has terminado de entenderel concepto, te recomiendo que le vuelvas a echar un vistazo porque es de las cosas ms importantesde Node.js y es necesario que el concepto quede claro.Despus, hemos visto cmo hacer uso de la consola de node para imprimir texto y mostrar contenidode los objetos a travs de los mtodos que nos ofrece console. Hemos visto la diferencia entre lasalida normal y la de errores y cmo medir el tiempo con la consola. Sin duda mtodos muy tilespara ver qu es lo que va ocurriendo en nuestra aplicacinAdicionalmente, hemos visto cmo podemos valernos de las variables del entorno para podermodificar el comportamiento de nuestra aplicacin en funcin del valor de alguna de las variables.Adems, has aprendido a pasar parmetros a tu aplicacin de Node.js para ayudar a que tu aplicacinfuncione.Adems, habrs aprendido a instalar Node.js y npm y cmo interactuar con la consola de Node. npmnos ofrece muchas opciones que no hemos dudado en ver una a una, como instalar o desinstalarpaquetes, cmo 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 captuloy nos hemos asegurado de que funciona correctamente.En el siguiente captulo, veremos temas ms avanzados como exportacin/importacin de ficherosen nuestra aplicacin con require, organizacin de los archivos de nuestra aplicacin, emisin deeventos y ms cosas que tienes por descubrir. No te las pierdas!

  • Adentrndonos en Node.js

    Ahora que ya tenemos los conceptos bsicos sobre Node.js, podemos empezar a jugar con conceptosy funciones que sonms complejas. Estoy seguro de que es lo que estabas deseando, verdad? A nadiele gustan las presentaciones, son aburridas y odiosas pero, al menos en este caso, estaba totalmentejustificada. Lo prometo!Este captulo podemos considerarlo como la planta baja de nuestra casa, ya que sobre todos estosfundamentos comenzaremos a profundizar en la tercera parte cuando nos metamos en faena conExpress.Basta de chchara. Vamos a ponernos manos a la obra!

  • Gestin de dependencias conpackage.jsonNode.js implementa CommonJS para distribuir paquetes lo cual ayuda a que todo este proceso estbastante extendido. Esto hace que, si creas una aplicacin, la puedas distribuir fcilmente a travsde npm para que pueda ser instalada por cualquiera.Pero hay una cosa que tienes que tener en cuenta. Tu aplicacin puede depender por ejemplo deExpress, pero Express a su vez, tiene una serie de dependencias que necesita para funcionar, que asu vez pueden necesitar ms 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 travs de npm,viene sin la carpeta node_modules en la cual se instalan todas las dependencias.Es probable que te ests preguntando

    Si Express usa como dependencia a connect, puedo hacer yo require('connect')yusarlo yo tambin?

    Realmente no. Tampoco es buena idea. La gestin de dependencias en cadena que usa Node.js (y lamayora de los lenguajes), est pensada as para que las versiones no den conflictos entre si. Voy aintentar explicarlo con un ejemplo ms grfico.Imagina por un momento, que eres carpintero. La programacin es muy complicada y has decididobuscar fortuna con otra profesin. Te has bajado de Google un diseo de rueda de carruajeespectacular as que, diseas tu carruaje alrededor de ese diseo de rueda, para que encajeperfectamente. Hasta ahora todo bien.Pero decides llevar tu carruaje a una feria para mostrarlo a posibles compradores. En el camino, sete rompe una rueda del carruaje. Un compaero que pasa cerca, se ofrece a prestarte una de susruedas. Desmontas la tuya y nada. No entra la nueva rueda. Tu carruaje depende de la versinde la rueda que te descargaste de Google. La otra no funciona. Ciertamente podras hacer algunosajustes a tu carro y usar la otra rueda, pero no es lo ideal.Por ello, si realmente quieres, puedes usar connect de Express usando algo as:

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

    Pero si el da de maana, Express actualiza su versin de connect es muy probable que tu aplicacindeje de funcionar correctamente por lo que, lo mejor, es especificar la versin que quieres usar entus dependencias.

  • Gestin de dependencias con package.json 37

    En el archivo package.json es donde colocamos toda esta informacin adems de ms cosas sobrenuestro paquete. Quiz por el nombre hayas descubierto que el archivo tiene una estructura JSON.No obstante, antes de meternos de lleno, tenemos que hablar de otra cosa.

    Versionado semnticoAntes de meternos con el archivo en s, me gustara hablar del versionado semntico (semver), quees usado tanto por Node.js como por los paquetes y tendremos que usarlo en cuanto definamos lasdependencias. Siguiendo nuestro ejemplo, sera la forma de catalogar la versin de las ruedas.Cuentan las leyendas, que en tiempos ancestrales no exista esta forma de versionar el software.Todos recordaremos la famosa etiqueta Beta de Gmail que, en aquel momento quera decir: Estofunciona pero vamos a aadir ms cosas y eventualmente puede romperse! (eso no es lo que hoy enda significa Beta).Adems, tenamos las versiones Alpha que estaban en un estado anterior a Beta. No obstante, estil porque permite a la empresa probar el software y ofrecer feedback sobre cosas como Interfaz,Velocidad y Usabilidad.Hoy en da, las cosas han cambiado un poco conforme las metodologas han ido avanzando. Porello, tambin lo ha hecho la forma en que ponemos las versiones de las versiones (vlgame laredundancia). Hoy en da, lo que est de moda son las versiones del tipo x.y.z. Si no te gusta lamoda no te preocupes. Esta moda ha llegado por un motivo y es el hecho de darle significado a lasversiones (de ah el nombre de versionado semntico).

    x - Cambio mayor : Este tipo de cambio es un cambio serio en la aplicacin de manera quees drsticamente diferente de anteriores versiones. Normalmente, si esta fuera una aplicacinde pago, es el tipo de cambio que te costaran dinero.

    y - Cambio menor : Has aadido algo nuevo que mejora significativamente el producto obien has cambiado algo que estaba causando muchos problemas y/o era malicioso o si estseliminando algo. Han de ser retrocompatibles con lo anterior.

    z - Parche : Correcciones de errores. Han de ser retrocompatibles con lo anterior.

    En Node.js y en los paquetes, esta es la metodologa que se usa para versionar cada uno de lospaquetes que podemos instalar con npm. No obstante, aceptan una modificacin, el - por lo queeste tipo de versin 0.30.1-2 es vlida para paquetes npm, pero no en el mundo semver. A mipersonalmente este aadido me parece superfluo ya que, nada te impide aumentar la versin z parahacer ajustes, no?En general, no deberas usar 1.X.X a no ser que la aplicacin sea estable. Seguro que dudas de si tuaplicacin es lo suficientemente estable como para ponerle ese 1.0.0 que tanto gusta. Quiz algo quete ayude es hacerte esta otra pregunta:

    Est la aplicacin en produccin?

  • Gestin de dependencias con package.json 38

    Si has respondido s, es que ya debera haber pasado a esa versin as que Corre!Y no est Node.js en produccin?

    Hombre no nos pongamos quisquillosos. En realidad, Node.js no es que est en produccin si noque se usa para aplicaciones que se ponen en produccin. No obstante, podramos considerarlo comoen produccin. Lo que ocurre, es que est en continuo cambio y hay muchas partes del cdigo queaun no funcionan todo lo estable que le gustara al equipo que est detrs de su desarrollo.

    Y qu pasa con las versiones Alpha y Beta ahora?No te preocupes, aun no han desaparecido. Puedes usarlas si es que quieres y, en cierta manera, leaaden al cdigo ms significado. Para crearlas, solo tienes que aadir al final la versin que quieras.Por ejemplo 0.1.2-3-beta o 0.1.2-4-alpha. Aqu tienes un ejemplo de cmo evala node semverlas versiones:1 0.1.2-7 > 0.1.2-7-beta > 0.1.2-6 > 0.1.2 > 0.1.2beta

    Recuerda que NPM siempre intenta escoger la versin ms actualizada del paquete disponible,mientras no seas ms especfico.

    Descubre ms

    Si te interesa saber ms sobre la especificacin, puede que quieras echar un vistazo a loque te cuentan en su pgina web (en ingls) No te lo pierdas! - http://semver.org/

    Estructura del archivoHay dos elementos que son imprescindibles en un archivo package.json. Sin ellos, no funcionarbien. Especialmente con versiones antiguas de Node.js. El primer elemento es el nombre del paquete.Este nombre no puede contener espacios vacos ni caracteres extraos. S, la cuenta como caracter,puetas!El segundo elemento no es otro que la versin del paquete que estamos creando. Puedes usar porejemplo la 0.0.1 para empezar.No obstante, la tarea quems nos preocupa en este captulo, no es otra que gestionar las dependenciasde nuestra aplicacin. As que, aadamos a la lista de imprescindibles, la dependencia de mdulos(con sus versiones) que necesitamos para usar el paquete.Veamos un breve ejemplo:

    http://semver.org/

  • Gestin de dependencias con package.json 39

    1 {2 "name": "mi-aplicacion",3 "description": "Un paquete de prueba que nunca ver la luz",4 "author": "Uno que aprende ",5 "version" : "0.0.1",6 "dependencies": {7 "express": ">=3.2.0"8 },9 "engine": "node 0.10.x"10 }

    Como ves, los parmetros son bastante sencillos de entender. Todos estos parmetros son vlidos eneste archivo y, lo que hacen, es dotar de ms significado al paquete en s. Si fueramos a distribuir elpaquete para que lo pudieran descargar terceros, sera sin duda buena idea el aadir estos parmetros.Como ves, le estamos facilitando un nombre, una descripcin, un autor (ficticio) y las dependencias.Como habrs observado, las dependencias estn especificadas con notacin semver.Quiz te hayas fijado en que la dependencia que hemos indicado de Express es de la versin 3.2.0o mayor.Para instalar las dependencias solo tenemos que ejecutar el siguiente comando:

    1 npm install

    Y vers como automticamente empieza a bajarse las dependencias indicadas. En este caso solamenteExpress. Node intenta buscar la versin ms actualizada posible que cumpla con los requisitos quehemos puesto para cada paquete. Si por lo que sea no hay versin del paquete que cumpla con losrequisitos, la instalacin fallar.Aunque hayamos indicado que queremos las versiones mayores a 3.2.0 esto no significa que seauna buena prctica. Realmente estamos diciendo, quiero estar a la ltima y, cada vez que ejecutemosel anterior comando nos traeremos la ltima versin de la dependencia genial, no?

    No

    El da que por algn casual salga Express 4.0.0 es muy probable que tu aplicacin deje de funcionarporque los cambios no tienen por qu ser retrocompatibles. As que recuerda tener mucho cuidadocon todo esto. Recuerda que

    Las versiones sin control, no sirven de nada

  • Gestin de dependencias con package.json 40

    Dependencias para desarrolloImaginemos que queremos, por algn casual, instalar dependencias que luego no vayamos a instalaren produccin, pero adems, queremos que si alguien nuevo entra a trabajar en el proyecto, puedadisponer de ellas correctamente. Que no se te ocurre nada? Veamos Quiz esto no te suene, peroaunque es un tema que no vamos a tratar en el libro, la gran mayora de este tipo de dependenciasson para instalar software que nos permita realizar pruebas sobre nuestra aplicacin.Para ello, podemos aadir un parmetro ms a nuestro archivo package.json:1 {2 "name": "mi-aplicacion",3 "description": "Un paquete de prueba que nunca ver la luz",4 "author": "Uno que aprende ",5 "version" : "0.0.1",6 "dependencies": {7 "express": ">=3.2.0"8 },9 "devDependencies": {10 "mocha": "1.11.X"11 }12 }

    Para instalarla, bastar con hacer el mismo npm install ya que, por defecto Node.js entiende queestamos en desarrollo. Si quieres evitarlo no tienes ms que ejecutar el siguiente comando:1 $ npm install --production

    Por otro lado,si la variable de entorno NODE_ENV tiene el valor de production, los paquetes dedesarrollo no se instalarn. Y qu pasa si eres un vaquero y quieres instalar las dependencias dedesarrollo en un entorno que est marcado como production? Pues tienes otra opcin:1 $ npm install --dev

    Instalar un paquete y guardarlo como dependenciaComo aprenders si sigues disfrutando de las bondades de Node.js, npm es un buen colega tuyo. Unode esos que se preocupa de ti y te echa un cable cuando puede. Conforme avances en tu desarrollo,a menudo te encontrars con un problema similar a este:Vaya, quiero instalar un conector contra una base de datos MySQL. Voy a buscar algo en GoogleHumm este paquete de node-mysql parece ser lo que necesito. Vaya, ahora tengo que actualizar mipackage.json!No! npm nos ofrece un par de atajos para guardar nuestros paquetes tanto como dependenciasnormales como de desarrollo:

  • Gestin de dependencias con package.json 41

    1 $ npm install node-mysql --save2 $ npm install mocha --save-dev

    Estas marcas opcionales, nos permiten actualizar automticamente nuestro archivo package.json.--save se encargar de guardarlo en la seccin de dependenciesmientras que --save-dev loguardar en devDependencies.Esto si que es un gran amigo!

    Descubre ms

    Si te interesa saber ms sobre el archivo package.json, puedes encontrar una guainteractiva en la que tratan todos los campos que se pueden usar (muchos ms de losque hemos visto aqu) en la pgina de Nodejitsu - No te la pierdas!

    http://package.json.nodejitsu.com/

  • Exportando en Node.jsHasta ahora hemos estado importando paquetes a nuestra aplicacin cigamente. Por ejemplo:

    1 var util = require('util');

    Pero, qu pasa si queremos crear un archivo que queramos requerir? En este captulo vamos a vercomo hacerlo. Separar el cdigo es buena idea y es algo que trataremos en el prximo captulo contodo detalle.Node.js implementa el estndar que cre CommonJS para cargar mdulos, esto facilita mucho latarea de exportar e importar archivos en Node.js. Como no pretendo que nadie que lea este libroconozca el estndar de CommonJS, vamos a explicarlo brevemente.

    Exportando con el objeto exportsTodos los scripts de Node exponen un objeto exports de manera que al requerirlos, tenemos lo quehaya en ese objeto. Veamos un breve ejemplo con comentarios de lo que va ocurriendo internamente:

    tweets.js

    1 // var exports = {};23 var misTweets = ['Tweet 1', 'Tweet 2', 'Tweet 3', 'Tweet 4'],4 misOtrosTweets = ['Me encanta escuchar Justin Beaver', 'Me gusta Crepscu\5 lo'];67 exports.tweets = misTweets;8 exports.cuentaTweets = function() {9 return misTweets.length + misOtrosTweets.length;10 };1112 // exports = {13 // tweets : misTweets,14 // cuentaTweets : function() { ... }15 // };

  • Exportando en Node.js 43

    En los comentarios puedes ir viendo cmo se va comportando la variable exports. Podemosaadir tantas propiedades y funciones como queramos. Estas funciones tendrn acceso al resto delcontenido del archivo pero no podremos acceder a nada que no haya sido exportado. En nuestro caso,queremosmantener en secreto nuestros Tweets sobre nuestros gustosNo porque sean escandalosos(lo son?), si no porque a nadie le interesan. No obstante, los aadimos a la cuenta de TweetsVeamos cmo importarlo:

    app.js1 var tweets = require('./tweets');23 console.log(tweets.tweets);4 // [ 'Tweet 1', 'Tweet 2', 'Tweet 3', 'Tweet 4' ]56 console.log(tweets.cuentaTweets());7 // 489 console.log(tweets.misOtrosTweets);10 // undefined

    Lo primero que observamos es que en el require tenemos que poner ./ antes del nombre del archivo,indicando que el archivo est en elmismo directorio en el que est app.js. Si lo hubiramos guardadoen la carpeta aplicaciones, tendramos que haber puesto algo como aplicaciones/tweets. Laextensin podemos omitirla si queremos ya que Node.js se encargar de encontrarla por su cuenta.Como ves, ahora la variable tweets contiene el valor de exports del contenido del archivotweets.js y, como podrs comprobar, no tenemos acceso al valor de misOtrosTweets pero la funcincuentaTweets ha accedido a su longitud correctamente.Cabe destacar que el llamar tweets a la variable es solo una convencin de llamar a la variable igualque al fichero que se importa, podramos haber hecho esto perfectamente:

    1 var noSonTweets = require('./tweets');2 console.log(noSonTweets.tweets);3 // [ 'Tweet 1', 'Tweet 2', 'Tweet 3', 'Tweet 4' ]

    Exportando con module.exportsQu es esto? No es lo mismo? La verdad es que no. Son muy parecidos. exports es realmente unpequeo ayudante de module.exports y es lo que realmente es devuelto a la hora de importarlo,no exports. exports lo que hace es recoger todas las propiedades y funciones y aadirlas a

  • Exportando en Node.js 44

    module.exports si ste ltimo no tiene ya algo. Si hemos aadido algo a module.exports losexports sern obviados.Entonces, si en el ejemplo anterior ponemos esto:

    tweets.js

    1 module.exports = 'MIS TWEETS';2 exports.cuentaTweets = = function() {3 return 4;4 };

    Y ahora hacemos esto:

    app.js

    1 var tweets = require('./tweets');23 console.log(tweets.cuentaTweets);4 // TypeError: Object MIS TWEETS has no method 'cuentaTweets'

    Como ves, nuestra intil aplicacin ha obviado por completo la funcin cuentaTweets ya quemodule.exports haba tenido lugar.module.exports puede tomar el valor de cualquier cosa de JavaScript: ya sea una funcin, unamatrizo una clase:

    tweets.js

    1 function Tweets (cuenta) {2 this.cuenta = cuenta;3 }45 Tweets.prototype.leerTweets = function() {6 console.log('Leyendo tweets de "%s"',this.cuenta);7 }89 module.exports = Tweets;

  • Exportando en Node.js 45

    app.js

    1 var Tweets = require('./tweets');23 var belelros = new Tweets('@Belelros'),4 funcion13 = new Tweets('@Funcion13');56 belelros.leerTweets(); // Leyendo tweets de "@Belelros"7 funcion13.leerTweets(); // Leyendo tweets de "@Funcion13"

    Como ves, hemos separado el cdigo de la clase a otro archivo y ahora podemos crear objetos de esetipo fcilmente, cada uno con su propio valor.

    Algunas aclaracionesCabe destacar varias cosas para evitar confusiones:

    Las llamadas a exports o module.exports han de ser inmediatas en el cdigo, no pueden estardentro de un callback ni nada parecido. Esto no funcionar por ejemplo:

    1 setTimeout(function() {2 module.exports = 'OLA K ASE';3 }, 100);

    Asociar propiedades y mtodos a module.exports es exactamente lo mismo que hacerlo aexports. Por ejemplo esto:

    1 module.exports.saludar = function(nombre) {2 console.log('Hola %s!',nombre);3 };

    Es idntico a esto:

  • Exportando en Node.js 46

    1 exports.saludar = function(nombre) {2 console.log('Hola %s!',nombre);3 };

    module es la variable global dentro de un archivo. Funciona de la misma manera que windowen el navegador.

    Eligiendo el mtodo adecuadoEn este momento estars teniendo un cacao mental y estars pensando y cundo elijo uno u otro?Yo he estado ah. La verdad es que es cuestin de preferencias porque realmente, module.exportses exactamente lo mismo que exports. No obstante, para evitar confusiones, lo mejor es quedarsecon module.exports.Las reglas son las siguientes:

    Si vamos a crear una clase y queremos exportarla, lo ideal es definir la clase, sus prototipos yluego asociarla directamente a module.exports.

    tweets.js

    1 function Tweets (cuenta) {2 this.cuenta = cuenta;3 }45 Tweets.prototype.leerTweets = function() {6 console.log('Leyendo tweets de "%s"',this.cuenta);7 }89 module.exports = Tweets;

    Si vamos a crear un objeto con propiedades, como en un fichero de configuracin, haremosalgo as:

  • Exportando en Node.js 47

    config.js

    1 module.exports = {2 usuario : 'root',3 clave : 'root',4 servidor : 'localhost'5 };

    Pasando parmetros a requireA veces puede que quieras personalizar lo que obtienes de un require pasando un parmetro. Estopuede ayudarte enormemente a reducir la cantidad de cdigo que necesitas escribir. Pongamosel ejemplo de que necesitas conectar a dos bases de datos y tienes un mdulo que se encarga dedevolverte algo para que puedas conectar:

    bdatos.js

    1 var config = {2 usuario : 'root',3 pass : 'root',4 servidor : 'localhost'5 };67 module.exports = function(opciones) {8 var usuario = opciones.usuario || config.usuario,9 pass = opciones.pass || config.pass,10 servidor = opciones.servidor || config.servidor;1112 return {13 consulta : function() {14 console.log('Haciendo consulta al servidor %s con el usuario %s', ser\15 vidor, usuario);16 }17 }18 };

  • Exportando en Node.js 48

    app.js

    1 var local = require('./bdatos')({ 'usuario' : 'Trololo' }),2 remoto = require('./bdatos')({ 'servidor' : 'remoto' })34 local.consulta();5 // Haciendo consulta al servidor localhost con el usuario Trololo6 remoto.consulta();7 // Haciendo consulta al servidor remoto con el usuario root

    En bdatos creamos un objeto con las variables de