Sobre Node, npm, package.json y Express

Vamos a repasar alguno de los conceptos que conviene tener claros a la hora de trabajar con un proyecto de Node.

Si queréis instalaros un entorno de desarrollo os recomiendo que echéis un vistazo a estos dos screencasts de Nettuts+ sobre Node.

¿Qué es Node.js?

Node.js es una plataforma construida sobre el motor de JavaScript de Google Chrome (V8) que permite un fácil y rápido desarrollo de aplicaciones escalables.

En otros terminos permite la ejecución de JavaScript en el lado del servidor.

Usos de Node.js

Las posibilidades que ofrece Node van más haya de un simple Web Server así es que muchos desarrolladores la utilizan como una herramienta más de Workflow.

Web server

Uno de los usos más comunes de Node es montarse un servidor HTTP. Para ello podemos utilizar el módulo http que viene incluido en el core de Node.

// Load the http module to create an http server.
var http = require('http');

// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello World\n");
});

// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);

// Put a friendly message on the terminal
console.log("Server running at http://127.0.0.1:8000/");

Workflow tool

La impresionante comunidad de Node ha desarrollado multitud de paquetes para hacer de Node una herramienta casi imprescindible en el proceso de desarrollo.

Lenguajes como CoffeeScript que compilan a JS, preprocesadores CSS como Stylus o linters de JS como JSHint corren bajo Node.

Pero esto no sería tan bonito sin un gestor de tareas JavaScript como Grunt o Gulp que permiten centralizar y automatizar estás tareas para que con un simple comando o con un watcher tengamos CoffeScript compilado a JS, Stylus en CSS o JSHint pasado.

Ejemplo de Gruntfile.js:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    stylus: {
      compile: {
        options: {
          compress: true
        },
        files: {
          'stylesheets/xpressio.css': ['stylesheets/xpressio.styl']
        }
      }
    }
     
    watch: {
      stylus: {
        files: ['stylesheets/*.styl'],
        tasks: ['stylus']
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-stylus');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // Default task(s).
  grunt.registerTask('default', ['stylus', 'jshint']);

};

Node Packaged Manager (npm)

Todo este tipo de herramientas que comentaba (CoffeeScript, Stylus, JSHint, Grunt, Gulp, ...) están disponibles en el gestor de paquetes de Node, npm.

La enorme y activa comunidad de Node ha hecho que a día de hoy estén disponibles más de 55 400 paquetes.

El uso de npm es muy sencillo.

# Package installation
npm install <packageName>

# Global package installation (probably need sudo)
sudo npm install <packageName> -g

# Save package dependency on package.json
npm install <packageName> --save

# Save package as devDependency on package.json
npm install <packageName> --save-dev

Ejemplos prácticos:

# Grunt
sudo npm install grunt-cli -g

# CoffeeScript
sudo npm install coffee-script -g

# Stylus
sudo npm install stylus -g

# Grunt and Grunt plugins
npm install grunt --save-dev
npm install grunt-contrib-coffee --save-dev
npm install grunt-contrib-stylus --save-dev
npm install grunt-contrib-watch --save-dev

¿Para qué sirve el archivo package.json?

En este archivo, que debe estar en la raíz del proyecto, va a quedar reflejada la configuración del proyecto de Node tales como:

  • Nombre del proyecto.
  • Autor.
  • Versión.
  • Dependencias.
  • Scripts.
  • Repositorio Git.
  • Motor de Node.
  • ...

Tal y como se indica en la documentación del package.json:

The most important things in your package.json are the name and version fields. Those are actually required, and your package won't install without them. The name and version together form an identifier that is assumed to be completely unique. Changes to the package should come along with changes to the version.

El archivo package.json puede crearse con el asistente de npm:

npm init

Aquí un ejemplo de parte del package.json de Ghost:

{
  "name"        : "ghost",
  "version"     : "0.4.0",
  "description" : "Just a blogging platform.",
  "author"      : "Ghost Foundation",
  "homepage"    : "http://ghost.org",
  "keywords"    : [
    "ghost",
    "blog",
    "cms"
  ],
  "repository"  : {
    "type": "git",
    "url": "git://github.com/TryGhost/Ghost.git"
  },
  "bugs"        : "https://github.com/TryGhost/Ghost/issues",
  "contributors": "https://github.com/TryGhost/Ghost/graphs/contributors",
  "private"     : true,
  "licenses"    : [
    {
      "type": "MIT",
      "url": "https://raw.github.com/TryGhost/Ghost/master/LICENSE"
    }
  ],
  "main": "./core/index",
  "scripts": {
    "start": "node index",
    "test": "grunt validate --verbose"
  },
  "engines": {
    "node": "~0.10.0"
  },
  "engineStrict": true,
  "dependencies": {
    "bcryptjs": "0.7.10",
    "connect-slashes": "1.2.0",
    "downsize": "0.0.4",
    "express": "3.4.6",
    "express-hbs": "0.5.2",
    "when": "2.7.0"
  },
  "devDependencies": {
    "blanket": "~1.1.5",
    "grunt": "~0.4.1",
    "grunt-contrib-compress": "~0.5.2",
    "grunt-contrib-concat": "~0.3.0",
    "should": "~2.1.1",
    "sinon": "~1.7.3",
    "supertest": "~0.8.2"
  }
}

Express, un Web framework

Uno de los frameworks por excelencia cuando queremos montar un Web server con Node es Express.

Esta es la definición que podéis encontrar en la Web de Express:

Express is a minimal and flexible node.js web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications.

Nos facilita el manejo de:

  • Estáticos: ruta pública donde generalmente se alojan assets (CSS, images, JS).

      app.use(express.static(path.join(__dirname, 'public')));
    
  • Controladores: encargados de controlar las peticiones http.

      app.post('/login', function(req, res) {});
    
  • Sesiones y cookies:

      app.use(express.cookieParser('your secret here'));
      app.use(express.session());
    
  • Templates: ruta de la vistas y motor de templates (Handlebars, Jade, Mustache, ...).

      app.set('views', path.join(__dirname, 'views'));
      app.set('view engine', 'jade');
    
  • Preprocesador CSS:

      app.use(require('stylus').middleware(path.join(__dirname, 'public')));
    
  • ...

Como cualquier paquete de Node su instalación es muy sencilla:

sudo npm install express -g

Una vez instalado podremos ver el usage con el flag -h.

express -h

Usage: express [options] [dir]

Options:

-h, --help          output usage information
-V, --version       output the version number
-s, --sessions      add session support
-e, --ejs           add ejs engine support (defaults to jade)
-J, --jshtml        add jshtml engine support (defaults to jade)
-H, --hogan         add hogan.js engine support
-c, --css <engine>  add stylesheet <engine> support (less|stylus) (defaults to plain css)
-f, --force         force on non-empty directory

Crear una WebApp con Express y que tenga soporte para sesiones y Stylus es tan sencillo como:

express --sessions --css stylus myapp

Si omitimos la configuración de la App, podemos ver lo sencillo que es manejar las peticiones y sus diferentes métodos:

var express = require('express');
var http = require('http');
var path = require('path');

var app = express();

app.get('/', function(req, res){
  // Do your stuff with request and response
});

app.post('/login', function(req, res){
  // Do your stuff with request and response
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Haciendo un breve resumen sobre los conceptos:

  • Node: permite la ejecución de JavaScript en el server además de servir como herramienta de desarrollo.
  • npm: es el gestor de paquetes de Node desde donde puedes instalar los módulos.
  • package.json: el archivo de configuración de un proyecto de Node.
  • Express: un Web framework que a menudo lo veréis en proyectos 100% Node.