domingo, 15 de enero de 2012

Empezando con Node.JS #nodejs #javascript

Tutorial de introducción a:



Aprovechando que llevo unos días dándole al node.js, voy a escribir un pequeña introducción a node.js. Con las cosas interesantes que he visto, y detalles para hacer más fácil el uso de node.js y evitar toda la investigación forense que he ido haciendo.

Una pequeña introducción y razón de ser:

Un intérprete y una librería:

Lo primero de todo una pequeña explicación de qué es node.js y por qué vale la pena darle una oportunidad.
Node.js en esencia es una máquina virtual de javascript con el motor V8 de google junto a un conjunto de librerías para desarrollo de servidor.  El V8 marcó un antes y un después en cuanto a rendimiento e hizo ponerse las pilas al resto de navegadores y ahora tenemos motores de javascript muy rápidos. Aunque el V8 está siempre a la vanguardia.



Un único lenguaje:

Node.js tiene como objetivo usar un único lenguaje tanto en backend como en frontend: javascript, así como llevar el rendimiento en el servidor a un nuevo nivel mediante la programación asíncrona (lo que promete .NET en su versión 4.5/5).

Ventajas de la programación asíncrona frente a threads y forks:

¿Qué ventajas tiene la programación asíncrona frente a la tradicional con threads o forks? Los threads y los forks consumen mucha memoria y recursos. Los threads además requieren de primitivas de sincronización, que suelen acabar en deadlocks o programación demasiado complicada. Hay un gráfico que compara nginx con apache en cuanto a memoria muy conocido. Nginx es conocido por tener un único thread y hacer I/O asíncrono, mientras que apache hace forks.


Si por cada petición se crea un fork del proceso, se acaba utilizando mucha memoria. Mientras que si por cada petición nos guardamos un estado asíncrono y ejecutamos código únicamente cuando llega un evento de I/O asíncrono, la eficiencia es mucho mayor: tanto en memoria como en CPU.

Sencillez y eficiencia:

Mientras que con PHP el servidor crea un fork por cada petición, o si se usa mediante fastcgi, hay un pool de servidores PHP esperando a recibir peticiones (cada uno consumiendo memoria y limitado al número de servidores procesos que puedas tener abiertos 20, 40...), con node.js hay un único proceso capaz de gestionar miles de peticiones de forma concurrente sin despeinarse. La memoria requerida baja varios ordenes de magnitud y se pueden tener muchísimas peticiones concurrentes y en espera (fundamental para websockets).

Pequeño servidor http en node.js:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

Node.js es monothread, es decir, que solo tiene un hilo de ejecución de usuario y no tiene forks de normal. El mismo proceso atiende todas las peticiones. Eso nos permite tener una gran parte de memoria común. Podemos tener un contador de visitas que es una variable en memoria. No hay que usar memoria compartida entre procesos ni extensiones raras.
Y no solo es que en un único proceso tenemos todo un servidor, sino que podemos tener varios a la vez. Podemos tener timers: setTimeout o setInterval, que se ejecutarán periódicamente tal y como lo haría un cron.

Empezando con Node.JS:

Instalación:

Lo primero que tenemos que hacer es bajarnos Node.JS. Desde unix podemos bajarnos el código fuente y compilarlo con los pasos típicos: ./configure && make && make install o desde el instalador de paquetes de nuestra distribución: apt-get, yum, pacman... En windows tenemos un instalador MSI.
http://nodejs.org/

Documentación:

El lenguaje de programación es Javascript, Y las APIs propias las podemos encontrar aquí:
http://nodejs.org/docs/v0.6.7/api/index.html

Hola mundo:

Una vez tengamos instalado node.js, deberíamos poder acceder al comando "node" desde la consola de nuestro SO. node archivo.js para lanzar un archivo javascript. Node es un simple intérprete/jitter de javascript, así que podemos hacer algo tan sencillo como un: console.log('Hola mundo'); y ejecutarlo. También podemos pegar el ejemplo básico de servidor en un archivo JS y lanzarlo. E ir al navegador y comprobar que funciona.

Particularidades de Node.JS:

Módulos para una fácil encapsulación:

De normal, javascript, al igual que PHP y C, tiene un ámbito global peligroso al que podemos acceder desde cualquier archivo que carguemos. Los llamados "includes" y que van en oposición a los lenguajes que usan "módulos" o "namespaces" como Python, Java o C#.
Está más que demostrado que los includes no son una buena idea y que los módulos permiten una mejor separación de código y evitan conflictos y problemas, así que con Node.JS han intentado enfocarlo a módulos.

Carpeta node_modules:

Para cargar un módulo se hace uso de la función require(ruta_al_módulo). Un módulo es un archivo .JS o una carpeta que contenga el archivo package.json. El archivo JS es un archivo javascript normal y corriente que tiene la particularidad de tener su propio ámbito. Y la forma de "exportar" funciones de ese ámbito es mediante el objeto exports. exports es un objeto inicialmente vacío que será lo que devuelva la función require cuando importemos un módulo y que establece la interfaz pública de ese módulo. Lo que se puede exportar es cualquier variable, aunque lo más común es exportar clases y métodos.
Si el parámetro que especificamos en el require, no es una ruta, se intentará buscar un módulo en la carpeta node_modules de la carpeta padre del archivo .js actual, del proyecto, o la carpeta node_modules global.
Esto nos permite tener y usar librerías externas con facilidad y comodidad. En el ejemplo de antes hemos visto: require('http'); Esto devuelve el objeto exports que se define en el módulo http, que estará definido en alguna carpeta node_modules.

Usando NPM

NPM es un proyecto de node que nos permitirá obtener, instalar y publicar módulos de node.js con una facilidad pasmosa entre una biblioteca de más de 6000 módulos opensource de todo tipo. NPM permite instalar en una carpeta node_modules local o en la global proyectos de Internet.
http://npmjs.org/

npm install express
npm install underscore
npm install mocha

npm install swig


express, underscore, swig y mocha son módulos de node.js que se instalan tan fácil como lanzar esos comandos desde una consola. Los proyectos que comento, (a excepción de swig) son proyectos muy populares en node.js

Express

Express es el framework más popular de node.js y simplifica el backend de servidor: con routing, vistas, configuraciones, servicio de estáticos con facilidad, modular y eficiente. Ayuda sustancialmente a empezar proyectos. Y tiene un comando "express" que permite generar un proyecto vacío en una carpeta con rutas y vistas.
http://expressjs.com/

express <path_a_carpeta_de_proyecto_a_crear>

Underscore

Underscore es una librería con un montón de funciones útiles de uso general. http://documentcloud.github.com/underscore/

Mocha

Mocha es un framework para hacer tests muy potente y sencillo. Que se usa en multitud de proyectos.
http://visionmedia.github.com/mocha/

Swig

Swig es un sistema de templating basado en django, twig y jinja, con herencia, compilado, muy rápido y compatible con express. Ideal si como yo, vienes de PHP con Twig.
http://paularmstrong.github.com/swig/

IDEs

Cualquier editor de texto puede valer para escribir código javascript. Si se hace TDD, el no tener autocompletado debería ser un mal menor en cuanto a calidad del código.

Respecto a IDEs que hacen la vida más fácil:
Conclusión

Desde que empezó node.js ya ha pasado un tiempo, y el producto ha madurado bastante. La comunidad ha crecido y ahora hay un montón de proyectos que dan soporte y forman todas las piezas necesarias para hacer un backend robusto y ágil.

Vale la pena darle un tiento a Node.JS
Al menos mientras Dart va haciendo su camino. Esperemos que introduzcan programación asíncrona con máquinas de estado como .NET 4.5, y dejen un IDE si no al nivel de lo que podemos conseguir con C#, sí a nivel de Java: entonces Dart será posiblemente la mejor opción para casi todo.

Ya iré comentando más cosas sobre el tema :)

1 comentario:

  1. hola amigo mira tengo una duda y e investigado y la verdad no he podido encontrar mucho, lo que tengo entendido es que nodejs debe estar en un servidor junto con mongo (o no necesariamente pero los 2 deben estar en la nube o no ??), bueno ahora mi duda es como puedo llamar al xx.js(el archivo de node) desde otro .js (pero desde el lado cliente, como para integrarlo en un html por ej ) se entiende??, si se entiende se puede hace y si se puede hacer como se hace??. Gracias y saludos

    ResponderEliminar