NodeJS & Express
 Desarrollo Web 2.0 Eficaz




                  Betabeers Barcelona 23/03/2012
Quienes somos?
Christophe Eymard
email : christophe@ravelsoft.com



Félix Delval
twitter : @fe_lix_
email : felix@ravelsoft.com




               https://github.com/ravelsoft
NodeJS
Qué es NodeJS
● LibUV : Una biblioteca desarrollada por
  Joyent en C
Qué es NodeJS
● LibUV : Una biblioteca desarrollada por
  Joyent en C
● V8 : El motor Javascript de Google Chrome
Qué es NodeJS
● LibUV : Una biblioteca desarrollada por
  Joyent en C
● V8 : El motor Javascript de Google Chrome
● Runtime en Javascript
Qué es NodeJS
● LibUV : Una biblioteca desarrollada por
  Joyent en C
● V8 : El motor Javascript de Google Chrome
● Runtime en Javascript
● Multi-Plataforma : Windows, Linux, OS X
Qué es NodeJS
● LibUV : Una biblioteca desarrollada por
  Joyent en C
● V8 : El motor Javascript de Google Chrome
● Runtime en Javascript
● Multi-Plataforma : Windows, Linux, OS X
● NPM : Package Manager (www.npmjs.org)
Porque NodeJS
● Un Sólo Hilo
  ○ ¡ (casi) adios mutex y race-condition !
Porque NodeJS
● Un Sólo Hilo
  ○ ¡ (casi) adios mutex y race-condition !
● Asíncrono (Non Blocking) :
   ○ Uso óptimo del CPU
Porque NodeJS
● Un Sólo Hilo
  ○ ¡ (casi) adios mutex y race-condition !
● Asíncrono (Non Blocking) :
   ○ Uso óptimo del CPU
   ○ « scaling » más evidente : más procesos y un load-
     balancer
Synchronous vs. Asynchronous
Porque NodeJS
● Un Sólo Hilo
  ○ ¡ (casi) adios mutex y race-condition !
● Asíncrono (Non Blocking) :
   ○ Uso óptimo del CPU
   ○ « scaling » más evidente : más procesos y un load-
     balancer
● Compartir código entre cliente e servidor
Porque NodeJS
● Un Sólo Hilo
  ○ ¡ (casi) adios mutex y race-condition !
● Asíncrono (Non Blocking) :
   ○ Uso óptimo del CPU
   ○ « scaling » más evidente : más procesos y un load-
     balancer
● Compartir código entre cliente e servidor
● V8
V8 en el mundo Real (más o menos)




                         fuente: http://shootout.alioth.debian.org
Desarrollar en NodeJS
● Programación por callbacks
Desarrollar en NodeJS
● Programación por callbacks
  ○ Parecido a request AJAX
Desarrollar en NodeJS
● Programación por callbacks
  ○ Parecido a request AJAX
  ○ « Hilos cooperativos »
Desarrollar en NodeJS
● Programación por callbacks
    ○ Parecido a request AJAX
    ○ « Hilos cooperativos »
●   El event-loop
Desarrollar en NodeJS
● Programación por callbacks
    ○ Parecido a request AJAX
    ○ « Hilos cooperativos »
●   El event-loop
    ○ epoll / kpoll / etc.
Desarrollar en NodeJS
● Programación por callbacks
    ○ Parecido a request AJAX
    ○ « Hilos cooperativos »
●   El event-loop
    ○ epoll / kpoll / etc.
    ○ Llama las callbacks cuando tienen su resultado
Desarrollar en NodeJS
● Programación por callbacks
    ○ Parecido a request AJAX
    ○ « Hilos cooperativos »
● El event-loop
  ○ epoll / kpoll / etc.
  ○ Llama las callbacks cuando tienen su resultado
● ... hay que respetarle
Desarrollar en NodeJS
● Programación por callbacks
    ○ Parecido a request AJAX
    ○ « Hilos cooperativos »
● El event-loop
  ○ epoll / kpoll / etc.
  ○ Llama las callbacks cuando tienen su resultado
● ... hay que respetarle
  ○ Cuidado con el uso del CPU
Desarrollar en NodeJS
● Programación por callbacks
    ○ Parecido a request AJAX
    ○ « Hilos cooperativos »
● El event-loop
  ○ epoll / kpoll / etc.
  ○ Llama las callbacks cuando tienen su resultado
● ... hay que respetarle
  ○ Cuidado con el uso del CPU
  ○ process.nextTick
Hello World

   var http = require('http');

   function miRespuesta(req, res) {
     res.writeHead(200, {'Content-Type':
   'text/plain'});
     res.end('Hello Worldn');
   }
   var server = http.createServer(miRespuesta)
   server.listen(1337, '127.0.0.1');
Mal Ejemplo : Fibonacci
Mal Ejemplo : Fibonacci
      var http = require('http');

      function fibonacci(n) {
          if (n <= 1) return n;
          else return fibonacci(n - 1) + fibonacci(n - 2);
      }
      http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type':
      'text/plain'});
        if (req.url == "/fibo")
          res.end("Fibo : " + fibonacci(33)); // OUCH
        else
          res.end('Hello Worldn');
      }).listen(1337, '127.0.0.1');
Mal Ejemplo II, pero mejor
var http = require("http")
                                               http.createServer(function (req, res) {
function fibonacci(n, cbk) {                      res.writeHead(200, {'Content-Type':
   if (n <= 1) cbk(n);                         'text/plain'});
   else fibonacci(n - 1, function(_n_1) {         if (req.url == "/fibo") {
       process.nextTick(function() {                  fibonacci(33, function(fibres) {
          fibonacci(n - 2, function( _n_2) {             res.end('Fibo: ' + fibres + 'n');
               cbk(_n_1 + _n_2)                       })
           })                                     } else {
       })                                             res.end('Hello Worldn');
  })                                              }
}
                                               }).listen(1337, '127.0.0.1');
Express
Express y su comunidad

+ de 5500 watchers

+ de 540 forks

+ de 100 issues abiertas



                           source : github.com
¿ Que propone ?
● Router de URL
  Con get, post,...
¿ Que propone ?
● Router de URL
  Con get, post,...

● Facilidades para motores de plantillas:
  Jade, EJS, JinJS, ...
¿ Que propone ?
● Router de URL
  Con get, post,...

● Facilidades para motores de plantillas:
  Jade, EJS, JinJS, ...

● Middleware via Connect
   y en cada función de routing
¿ Que propone ?
● Router de URL
  Con get, post,...

● Facilidades para motores de plantillas:
  Jade, EJS, JinJS, ...

● Middleware via Connect
   y en cada función de routing

● focus en alta rendimiento
● muy buen test coverage
Base del routing
app.get('/post/:post', myfun);
app.get(/post/([^/]+)/?, my fun);

matched :
  /post/123
  /post/foobar
  /post/foobar

not matched : /post/foo/bar
Plantillas con Jade
!!! 5
html
  head
    title Blog
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    #container
      block content
Instalación



# npm install -g express
Hello, World!

var app = express.createServer();

app.get('/', function(req, res){
    res.send('Hello World');
});

app.listen(3000);
Hello, World!
var express = require('express');
var app = express.createServer();

app.get('/', function(req, res){
    res.send('Hello World');
});

app.listen(3000);
El test más inútil del mundo
$ ab -n 10000 -c 1000 http://localhost:3000

Concurrency Level:      1000
Time taken for tests:   19.458 seconds
Complete requests:      100000
Requests per second:     5139.34 [#/sec] (mean)
Time per request:       194.578 [ms] (mean)
Time per request:       0.195 [ms] (mean, across all
concurrent requests)


                                    Intel i3 540 @ 3.07GHz / 8 GB RAM
Creación de
un blog básico
    con Express
Bootstrapping el proyecto
$ express misuperblog

$ cd misuperblog

$ npm install
Estructura de la applicación
misuperblog
|-- package.json /* Contiene las dependencias, autores */
|-- app.js          /* Archivo principal de la applicación */
|-- public         /* Archivos estaticos */
| |-- images
| |-- stylesheets
| | `-- style.css
| `-- javascripts
|-- views          /* Contiene todo los templates */
| |-- index.jade
| `-- layout.jade
`-- routes        /* Routing y codigo de cada view */
    `-- index.js
El datastore
var Post = require ('./models/post');

p = new Post();
{ id: 1,
  title: undefined,
  body: undefined,
  createdAt: Fri, 23 Mar 2012 14:23:30 GMT }

p.save();   Post.all();   Post.get();
En conclusión !
Node.js :
● V8         → Velocidad
● Libuv      → Asíncrono
● Javascript → Languaje único

Express :
● Routing potente
● Plantillas modulares
● Middleware
Buenas referencias
http://nodejs.org/
http://visionmedia.github.com/masteringnode/
http://expressjs.com/
http://nodeup.com/
http://nodejs.org/



Los gurus
https://github.com/substack
https://github.com/isaacs
https://github.com/visionmedia
https://github.com/felixge
¿ Algunas preguntas?
Alternativas a los Callbacks
● StreamlineJS
● node-fibers
● async/step
Bonus : el mal ejemplo con
Streamline
if (!require('streamline/module')(module))
return;

                                             http.createServer(function (req, res, _) {
var http = require("http")
                                                 res.writeHead(200, {'Content-Type':
                                             'text/plain'});
function fibonacci(n, _) {
                                                 if (req.url == "/fibo")
  if (n <= 1) return n;
                                                     res.end('Fibo: ' + fibonacci(33, _) +
  var res = fibonacci(n - 1, _);             'n');
  process.nextTick(_);                           else
  return res + fibonacci(n - 2, _);                  res.end('Hello Worldn');
}                                            }).listen(1337, '127.0.0.1');

Creación de aplicaciones web con Node.js y Express

  • 1.
    NodeJS & Express Desarrollo Web 2.0 Eficaz Betabeers Barcelona 23/03/2012
  • 2.
    Quienes somos? Christophe Eymard email: christophe@ravelsoft.com Félix Delval twitter : @fe_lix_ email : felix@ravelsoft.com https://github.com/ravelsoft
  • 3.
  • 4.
    Qué es NodeJS ●LibUV : Una biblioteca desarrollada por Joyent en C
  • 5.
    Qué es NodeJS ●LibUV : Una biblioteca desarrollada por Joyent en C ● V8 : El motor Javascript de Google Chrome
  • 6.
    Qué es NodeJS ●LibUV : Una biblioteca desarrollada por Joyent en C ● V8 : El motor Javascript de Google Chrome ● Runtime en Javascript
  • 7.
    Qué es NodeJS ●LibUV : Una biblioteca desarrollada por Joyent en C ● V8 : El motor Javascript de Google Chrome ● Runtime en Javascript ● Multi-Plataforma : Windows, Linux, OS X
  • 8.
    Qué es NodeJS ●LibUV : Una biblioteca desarrollada por Joyent en C ● V8 : El motor Javascript de Google Chrome ● Runtime en Javascript ● Multi-Plataforma : Windows, Linux, OS X ● NPM : Package Manager (www.npmjs.org)
  • 9.
    Porque NodeJS ● UnSólo Hilo ○ ¡ (casi) adios mutex y race-condition !
  • 10.
    Porque NodeJS ● UnSólo Hilo ○ ¡ (casi) adios mutex y race-condition ! ● Asíncrono (Non Blocking) : ○ Uso óptimo del CPU
  • 11.
    Porque NodeJS ● UnSólo Hilo ○ ¡ (casi) adios mutex y race-condition ! ● Asíncrono (Non Blocking) : ○ Uso óptimo del CPU ○ « scaling » más evidente : más procesos y un load- balancer
  • 12.
  • 13.
    Porque NodeJS ● UnSólo Hilo ○ ¡ (casi) adios mutex y race-condition ! ● Asíncrono (Non Blocking) : ○ Uso óptimo del CPU ○ « scaling » más evidente : más procesos y un load- balancer ● Compartir código entre cliente e servidor
  • 14.
    Porque NodeJS ● UnSólo Hilo ○ ¡ (casi) adios mutex y race-condition ! ● Asíncrono (Non Blocking) : ○ Uso óptimo del CPU ○ « scaling » más evidente : más procesos y un load- balancer ● Compartir código entre cliente e servidor ● V8
  • 15.
    V8 en elmundo Real (más o menos) fuente: http://shootout.alioth.debian.org
  • 16.
    Desarrollar en NodeJS ●Programación por callbacks
  • 17.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX
  • 18.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos »
  • 19.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos » ● El event-loop
  • 20.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos » ● El event-loop ○ epoll / kpoll / etc.
  • 21.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos » ● El event-loop ○ epoll / kpoll / etc. ○ Llama las callbacks cuando tienen su resultado
  • 22.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos » ● El event-loop ○ epoll / kpoll / etc. ○ Llama las callbacks cuando tienen su resultado ● ... hay que respetarle
  • 23.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos » ● El event-loop ○ epoll / kpoll / etc. ○ Llama las callbacks cuando tienen su resultado ● ... hay que respetarle ○ Cuidado con el uso del CPU
  • 24.
    Desarrollar en NodeJS ●Programación por callbacks ○ Parecido a request AJAX ○ « Hilos cooperativos » ● El event-loop ○ epoll / kpoll / etc. ○ Llama las callbacks cuando tienen su resultado ● ... hay que respetarle ○ Cuidado con el uso del CPU ○ process.nextTick
  • 25.
    Hello World var http = require('http'); function miRespuesta(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); } var server = http.createServer(miRespuesta) server.listen(1337, '127.0.0.1');
  • 26.
    Mal Ejemplo :Fibonacci
  • 27.
    Mal Ejemplo :Fibonacci var http = require('http'); function fibonacci(n) { if (n <= 1) return n; else return fibonacci(n - 1) + fibonacci(n - 2); } http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); if (req.url == "/fibo") res.end("Fibo : " + fibonacci(33)); // OUCH else res.end('Hello Worldn'); }).listen(1337, '127.0.0.1');
  • 28.
    Mal Ejemplo II,pero mejor var http = require("http") http.createServer(function (req, res) { function fibonacci(n, cbk) { res.writeHead(200, {'Content-Type': if (n <= 1) cbk(n); 'text/plain'}); else fibonacci(n - 1, function(_n_1) { if (req.url == "/fibo") { process.nextTick(function() { fibonacci(33, function(fibres) { fibonacci(n - 2, function( _n_2) { res.end('Fibo: ' + fibres + 'n'); cbk(_n_1 + _n_2) }) }) } else { }) res.end('Hello Worldn'); }) } } }).listen(1337, '127.0.0.1');
  • 30.
  • 31.
    Express y sucomunidad + de 5500 watchers + de 540 forks + de 100 issues abiertas source : github.com
  • 32.
    ¿ Que propone? ● Router de URL Con get, post,...
  • 33.
    ¿ Que propone? ● Router de URL Con get, post,... ● Facilidades para motores de plantillas: Jade, EJS, JinJS, ...
  • 34.
    ¿ Que propone? ● Router de URL Con get, post,... ● Facilidades para motores de plantillas: Jade, EJS, JinJS, ... ● Middleware via Connect y en cada función de routing
  • 35.
    ¿ Que propone? ● Router de URL Con get, post,... ● Facilidades para motores de plantillas: Jade, EJS, JinJS, ... ● Middleware via Connect y en cada función de routing ● focus en alta rendimiento ● muy buen test coverage
  • 36.
    Base del routing app.get('/post/:post',myfun); app.get(/post/([^/]+)/?, my fun); matched : /post/123 /post/foobar /post/foobar not matched : /post/foo/bar
  • 37.
    Plantillas con Jade !!!5 html head title Blog link(rel='stylesheet', href='/stylesheets/style.css') body #container block content
  • 38.
  • 39.
    Hello, World! var app= express.createServer(); app.get('/', function(req, res){ res.send('Hello World'); }); app.listen(3000);
  • 40.
    Hello, World! var express= require('express'); var app = express.createServer(); app.get('/', function(req, res){ res.send('Hello World'); }); app.listen(3000);
  • 41.
    El test másinútil del mundo $ ab -n 10000 -c 1000 http://localhost:3000 Concurrency Level: 1000 Time taken for tests: 19.458 seconds Complete requests: 100000 Requests per second: 5139.34 [#/sec] (mean) Time per request: 194.578 [ms] (mean) Time per request: 0.195 [ms] (mean, across all concurrent requests) Intel i3 540 @ 3.07GHz / 8 GB RAM
  • 42.
    Creación de un blogbásico con Express
  • 43.
    Bootstrapping el proyecto $express misuperblog $ cd misuperblog $ npm install
  • 44.
    Estructura de laapplicación misuperblog |-- package.json /* Contiene las dependencias, autores */ |-- app.js /* Archivo principal de la applicación */ |-- public /* Archivos estaticos */ | |-- images | |-- stylesheets | | `-- style.css | `-- javascripts |-- views /* Contiene todo los templates */ | |-- index.jade | `-- layout.jade `-- routes /* Routing y codigo de cada view */ `-- index.js
  • 45.
    El datastore var Post= require ('./models/post'); p = new Post(); { id: 1, title: undefined, body: undefined, createdAt: Fri, 23 Mar 2012 14:23:30 GMT } p.save(); Post.all(); Post.get();
  • 46.
    En conclusión ! Node.js: ● V8 → Velocidad ● Libuv → Asíncrono ● Javascript → Languaje único Express : ● Routing potente ● Plantillas modulares ● Middleware
  • 47.
  • 48.
  • 49.
    Alternativas a losCallbacks ● StreamlineJS ● node-fibers ● async/step
  • 50.
    Bonus : elmal ejemplo con Streamline if (!require('streamline/module')(module)) return; http.createServer(function (req, res, _) { var http = require("http") res.writeHead(200, {'Content-Type': 'text/plain'}); function fibonacci(n, _) { if (req.url == "/fibo") if (n <= 1) return n; res.end('Fibo: ' + fibonacci(33, _) + var res = fibonacci(n - 1, _); 'n'); process.nextTick(_); else return res + fibonacci(n - 2, _); res.end('Hello Worldn'); } }).listen(1337, '127.0.0.1');