Curso de node JS

  1. ¿Qué es NodeJS?
  2. Instalación de NodeJS
  3. Hola Mundo
  4. package.json
  5. Módulos
  6. Módulo para actualizar los cambios
  7. express
    1. Generación de un proyecto express
    2. Rutas con Express
    3. express sin express-generator
    4. Enviar un array a la vista
    5. Peticiones GET y POST
  8. Mysql
    1. Express con mysql - ejemplo básico
    2. Inserción con MySQL en nodeJS
    3. Mostrar errores Mysql
    4. Con parámetros
    5. Borrar
    6. Actualizar
    7. Ejercicio CRUD
    8. Consulta
    9. Sequelize
  9. Web Sockets con Express
  10. Imprimir los logs en un fichero de texto
  11. Handlebars - hbs
  12. Variables de sesión
  13. CORS
  14. JWT (JSON Web Tokens) usando express
  15. Subida de una imagen al servidor
  16. Middleware
  17. Servidor web sin express
  18. Publicar un plugin en npm
  19. Chokidar

¿Qué es NodeJS?

El lenguaje de programación Javascript está cada vez más extendido. Aunque fundamentalmente se ocupa de las funcionalidades que tiene una página web del lado de lo que el usuario está viendo, con nodeJS podrás programar con Javascript del lado del servidor. En este curso veremos como configurarlo, hacer consultas a la base de datos, comenzar proyectos desde cero, usar sockets...

Node.js es una plataforma para el desarrollo de aplicaciones en entorno del servidor mediante programación Javascript.

Presenta grandes ventajas en la implementación de aplicaciones que deben responder en tiempo real.

Pretende disputar terreno a lenguajes de servidor como PHP, Java, C# etc.

Instalación de NodeJS

  1. En Windows o Mac: NodeJS.
  2. En linux:
    sudo apt-get install -y npm

Hola Mundo

hola-mundo.jsconsole.log("hola Mundo")

Ejecutamos:

node hola-mundo.js

Crear un nuevo proyecto

npm init

package.json

package.json{
	"name": "proyecto", // Indicamos el nombre del proyecto
	"version": "0.0.0", // Indicamos la versión del proyecto
	"private": true,
	"scripts": {
		"start": "node ./bin/www" //Indicamos el archivo que se debe ejecutar para arrancar el proyecto
	},
	"dependencies": { 
		"body-parser": "~1.13.2",
		"cookie-parser": "~1.3.5",
		"debug": "~2.2.0",
		"express": "~4.13.1",
		"hbs": "~3.1.0",
		"morgan": "~1.6.1",
		"serve-favicon": "~2.3.0"
	}
}  

Al ejecutar npm install, se busca el archivo 'package.json' y se procede a instalar todos los módulos especificados en la propiedad 'dependencies'.

Módulos

Crear módulos

Un módulo es un fichero donde se crean grupos de funciones

aritmetica.jsvar PI=3.14;
function dividir(x1,x2){
    if (x2==0){
        mostrarErrorDivision();
    }else{
        return x1/x2;
    }
}

function mostrarErrorDivision() {
    console.log('No se puede dividir por cero');
}
exports.dividir=dividir;
exports.PI=PI;
main.jsvar mat=require('./aritmetica');

console.log('La división de 8/4='+mat.dividir(8,4));
console.log('El valor de PI='+mat.PI);

Para lanzarlo todo:

node main.js

Un módulo también puede ser una carpeta que contiene un conjunto de ficheros y subcarpetas.

Módulos del núcleo de nodejs

Algunos de los módulos del núcleo de Node.js son: os, fs, http, url, net, path, process, dns etc..

prueba.jsvar os=require('os');
console.log('Sistema operativo:'+os.platform());
console.log('Versión del sistema operativo:'+os.release());
console.log('Memoria total:'+os.totalmem()+' bytes');
console.log('Memoria libre:'+os.freemem()+' bytes');

Módulo para administrar el sistema de archivos: fs

var fs=require('fs');
//writeFile(donde_vamos_a_escribir, que_vamos_a_escribir, que_vamos_a_ejecutar_despues_de_escribir)
fs.writeFile('./archivo.txt','aaaaaa\nbbbbbb',function(error){
if (error)
    console.log(error);
else
    console.log('El archivo fue creado');
});
console.log('Última línea del programa');

Como nodejs es asíncrono, veremos que antes de mostrarse el texto "El archivo fue creado" se muestra el texto "Última línea del programa".

Instalación de un módulo

npm install socket.io
forma abreviada:npm i -S socket.io
npm i --g socket.io

El parametro --g hace que el módulo se instale de forma global y esté disponible para todos los usuarios en todos los proyectos. No podremos ejecutar este comando si no somos root.

Tras instalar un módulo, será recomendable reiniciar el servidor para que los cambios surtan efecto

Módulo para actualizar los cambios con express

npm i nodemon
package.json"scripts":{
    // "start": "node ./bin/www"
    "start": "nodemon ./bin/www"
}

Para parar el servidor:

npm stop
app.jsprocess.title = myApp;
scripts.json"scripts": {
    "start": "app.js",
    "stop": "pkill --signal SIGINT myApp" /*process title*/
}

Generación de un proyecto que utilice express

Tenemos dos opciones:

Para arrancar nuestra aplicación en el puerto 3000:

npm start

Si queremos parar node:

ps auxxx | grep node #Este comando nos permite ver los servicios de node que se están ejecutando
kill -9 1480 8573 #Paramos los servicios de node activos

Ejercicios rutas

Crear un nuevo proyecto con nodejs que implemente los siguientes enrutamientos:

Express sin express-generator

Nos permite materializar los ejemplos anteriores utilizando mucho menos código.

Hola Mundo con Express

En este ejemplo siempre mostraremos la misma página

npm init
npm i express
main.jsvar express=require('express');
var app=express();

app.get('/',function (req,res){
    res.send('Hola Mundo');
});

var server=app.listen(8888,function(){
    console.log('Servidor web iniciado');
});

Recuperación de páginas estáticas y recursos varios

Ya vimos como programar esto si usar el módulo Express. Veremos como se reduce el código usando este módulo.

public/index.html<a href="pagina1.html">PAGINA 1</a><br>
<a href="pagina2.html">PAGINA 2</a>
public/pagina1.htmlPAGINA 1
public/pagina2.htmlPAGINA 2
main.jsvar express=require('express');
    var app=express();

    app.use(express.static(__dirname + '/public'));

    var server=app.listen(8888,function(){
    console.log('Servidor web iniciado');
});

Recuperar los datos por get y post

Para recuperar los datos de un formulario HTML o los parámetros de una url debemos agregar además del framework Express una módulo para parsear los datos que llegan del navegador. Hay muchos módulos que hacen esta actividad el más común es el módulo 'body-parser'.

public/index.html<form action="envioporpost" method="post">
    <label for="">Envio por post</label>
    <input type="text" name="numero" size="10"><br>
    <input type="submit" value="Envío por POST">
</form>
<form action="envioporget">
    <label for="">Envío por get:</label>
    <input type="text" name="numero" size="10"><br>
    <input type="submit" value="Envío por GET">
</form>
main.jsvar express = require('express');
    var app=express();
    var bodyParser = require('body-parser');

    //especificamos el subdirectorio donde se encuentran las páginas estáticas
    app.use(express.static(__dirname + '/public'));

    //extended: false significa que parsea solo string (no archivos de imagenes por ejemplo)
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/envioporpost', function (req, res) {
    var num=req.body.numero;
    txt = 'El número recogido por post es el: '+num;
    res.send(txt);    
})

app.get('/envioporget', function (req, res) {
    var num=req.query.numero;
    var txt='El número regogido por get es el:' + num;
    res.send(txt);    
})


var server=app.listen(8888,function(){
    console.log('Servidor web iniciado');
});

Enviar un array a la vista

Creamos propiedades

routes/index.jsvar express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    var datos = { 
        dato1: 'Ulala' ,
        libros:[
            {titulo: 'Libro 1', autor: 'Pablo'},
            {titulo: 'Libro 2', autor: 'Monteserín'} 
        ]
    }
    res.render('index', datos);
});

module.exports = router;
views/index.hbs<h2>{{titulo}}</h2>
<ol>
    {{#each libros}}
        <li>{{titulo}} - {{autor}}</li>
    {{/each}}
</ol>

Este fichero index.hbs se cargará dentro de views/layout.hbs.

views/layout.hbs<!DOCTYPE html>
<html>
    <head>
        <title>{{title}}</title>
        <link rel='stylesheet' href='/stylesheets/style.css' />
    </head>
    <body>
        {{{body}}}
    </body>
</html>

Peticiones GET y POST

Ejemplo de petición GETrouter.get('/recuperar_escenas_obra', function(req, res, next) {
    const id = req.query.id;
Ejemplo de petición POSTrouter.post('/salvar_escenas', function(req, res, next) {
    const texto = req.body.texto;
    ...
}

Express con mysql - ejemplo básico

npm i mysql
routes/db.jsvar mysql=require('mysql');

var conexion=mysql.createConnection({
    host:'localhost',
    user:'root',
    password:'',
    database:'pruebasnodejs'
});

conexion.connect(function (error){
    if (error)
        console.log('Problemas de conexion con mysql');
    else
        console.log('se inicio conexion');
});


module.exports=conexion;

Estableciendo un pool de conexiones

Será necesario hacer un pool de conexiones si queremos hacer una aplicación que se ejecute en heroku con una cuenta gratuita, ya que esta se desconecta automáticamente tras un tiempo de inactividad.

const connectionPool = createConnectionPool({
    host:'localhost',
    user:'root',
    password:'',
    database:'pruebasnodejs'
});

const Connection = {
    query: (...params) => connectionPool.getConnection((err, conn) => conn.query(...params)),
};

Inserción con MySQL en nodeJS

routes/index.jsconst express = require('express');
const db=require('./db');
const router = express.Router();

router.get('/', function(req, res, next) {
    db.query('INSERT INTO libreria(titulo) VALUES ("El amor")');
    res.send('OK');
});

module.exports = router;

Mostrando errores

routes/index.js...
db.query('INSERT INTO libro SET titulo="El amor"' , function(error,filas){
    if (error) {            
        console.log('error en el listado: ' + error);
        return;
    }    
});
...

Con parámetros

http://localhost:3000?titulo=oso
routes/index.js...
var titulo = req.query.titulo;

db.query('INSERT INTO libro SET ?', {titulo:titulo}, function(error,filas){
    if (error) {            
        console.log('error en el listado: ' + error);
        return;
    }    
});
//Esto es el nombre del campo en la vista
//Esto es el nombre del campo en la tabla
...

Con varios parámetros

http://localhost:3000?titulo=oso&autor=Pablo
routes/index.js...
var titulo = req.query.titulo;
var autor = req.query.autor

db.query('INSERT INTO libro SET ?, ?', [{titulo:titulo}, {autor:autor}]
...

DELETE

Borrar

var id_recuperada = req.query.id_recuperada;
db.query('DELETE FROM libro WHERE ?', [{id:id_recuperada}

UPDATE

...
var titulo = req.query.titulo;
var autor = req.query.autor;
db.query('UPDATE alumnos SET ? WHERE ?',[{titulo:titulo}, {autor:autor}], function(error,filas){
...

Ejercicio CRUD

Hacer el alta, borrado y modificación de las películas de un videoclub. Las películas tienen los siguientes campos: id (entero, autoincrementado, clave primaria), título (varchar) y precio (int).

Consulta

db.query('SELECT * FROM libro', function(error,filas){
    if (error) {            
        console.log('error en el listado: ' + error);
        return;
    }    
    res.render('consultalibros',{libros:filas});

    /* Si usasemos AJAX...
    filas = JSON.stringify(filas);
    //Para que todo funcione, debo enviar una respuesta de vuelta, aunque sea vacía
    res.send(filas);
    */

});

Mostrar consulta ejecutada

consulta=db.query('SELECT * FROM alumnos WHERE ?', {cod:req.query.cb},function(error,filas){
    if (error) {            
        console.log('error en el listado: ' + error);
        return;
    }  
    console.log(consulta.sql);
    ...

Sequelize

Es un ORM para nodejs

npm i sequelize
mkdir lib
lib/db.jsconst Sequelize = require('sequelize')
//Creamos un Singleton (una clase que sólo devuele una única instancia que es la misma siempre)
let sequelize = null
module.exports = function setupDatabase(config){
    if(!sequelize) {
        sequelize = new Sequelize()
    }
}
models/user.jsconst Sequelize = require('sequlize')
setupDatabase = require('../lib/db')
module.exports = function setupUserModel(config){
    const sequelize = setupDatabase(config)
    return sequelize.define('user',{
        uuid: {
            Sequelize.STRING,
            allowNull: false  
        },
        mail:{
            type:Sequelize.STRING,
            allowNULL:false
        },
        password:{
            type:Sequelize.STRING,
                allowNULL:false
        }   
})
}

Web Sockets con Express

La parte del servidor

npm i socket.io
bin/wwwapp.io.attach(server);
app.jsvar app = express();
app.io = require('socket.io')();
...
app.io.on('connection', function(socket){  
    console.log('a user connected');

    socket.on('new message', function(msg){
        console.log('new message: ' + msg);
        app.io.emit('chat message', msg);
    });
});
Descargar recurso

Códigos adicionales que se pueden añadir al servidor

Llamada a los web sockets desde el controlador
index.jsrouter.post('/personajeSeleccionado', function(req, res, next) {
    ...
    var socket = req.app.get('socketio');
    socket.emit('fotoActualizada', "hello"); 
    ...
Llamar a un controlador desde el app.js
index.js
var index = require('./routes/index');
var heterminado = function(id_alumno){
    ...
}

module.exports = router;
//La siguiente línea tiene que estas, necesariamente, después de la anterior
module.exports.heterminado = heterminado;
app.jsvar index = require('./routes/index');
index.heterminado(msg.id_alumno);

El cliente (aplicación remota)

<input type="text" id="new-message">
<button id="enviar">Enviar</button>
<ul id="messages-area"></ul>


<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<!-- Usaríamos la siguiente línea en lugar de la anterior en el caso de estar desarrollando una aplicación con sockets integrada en el propio servidor (una vista jade o hbs, etc)-->
<script src="/socket.io/socket.io.js"></script>

<script>
    var socket = io.connect('http://localhost:3000');
    //Usaríamos la siguiente línea en lugar de la anterior en el caso de estar desarrollando una aplicación con sockets integrada en el propio servidor (una vista jade o hbs, etc)
    //var socket = io();
    function sendFunction() {
        socket.emit('new message', document.querySelector('#new-message').value);
    }
    
    socket.on('chat message', function(msg){
        var node = document.createElement("li");  
        node.textContent = msg;
        document.querySelector('#messages-area').appendChild(node);
    });

    document.querySelector('#enviar').addEventListener('click', sendFunction)
</script>

Imprimir los logs en un fichero de texto

npm i winston
./utils/logger.jsconst winston = require('winston');
  var logger = new (winston.Logger)({
    transports: [
      new (winston.transports.Console)(),
      new (winston.transports.File)({ filename: 'logs.log' })
    ]
  });
module.exports=logger;
index.jsvar winston = require('winston');
var logger = require("../utils/logger");
...
logger.log('info', 'La traza');

Handlebars - hbs

Evaluar si una variable existe{{#if cod}} 
        hola
{{/if}}
Evaluar si una variable no existe{{#unless cod}}
            valor
{{/unless}}

Variables de sesión

npm i express-session
app.jsvar session = require('express-session');
app.use(session({secret: '123456', resave: true, saveUninitialized: true}));
//Debemos declarar los routers que usen la sesión después de ínicializar la sesión 
app.use('/users', usersRouter);
routes/index.jsrouter.post('/login', function(req, res, next) {
    req.session.mail=req.body.mail;
    res.render('index');
});

Pasar variables de sesión a la vista

req.session.cod=cod;

CORS

Para permitir peticiones crossdomain añadiremos el siguiente middleware al fichero app.js; lo pondremos antes del resto de middlewares (primera llamada al método use).

app.jsapp.use(function(req, res, next) {
	res.header('Access-Control-Allow-Origin', '*');
	res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
	res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');

	if (req.method === 'OPTIONS') {
		res.end();
	} else {
		next();
	}
});

JWT (JSON Web Tokens)

Nos permiten loguearnos en una aplicación.

npm install jsonwebtoken
index.jsconst jwt = require('jsonwebtoken');
const SECRET = 'test';

router.post('/login', function(req, res, next) {
	const userName = req.body.userName;
	const password = req.body.password;
	if(userName === "pablo" && password === "monteserin"){
		const idRecuperadaDeLaBaseDeDatos = 1;
		const token = jwt.sign({ idRecuperadaDeLaBaseDeDatos }, SECRET);
		res.send({token});
	} else{
		res.send(403)
	}
});


router.get('/user-data', function(req, res, next) {
	const tokenData = jwt.verify(req.header('accessToken'), SECRET);
	res.send(tokenData);
});

Cuando usamos un token para validar una petición, dicho token nunca lo ponemos en el cuerpo de la petición (peticiones POST) ni en la URL (peticiones GET), sino en la cabecera del mensaje.

Ya que accessToken es el nombre del parámetro enviado en la cabecera, debemos establecer que lo admitiremos como parámetro de entrada en la cabecera.

app.jsapp.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, accesstoken");
  next();
});
Descargar ejmplo validación jwt

Subida de una imagen al servidor

Instalaremos el módulo muler.

npm i multer

Código del servidor

index.jsvar multer  =   require('multer');
var storage =   multer.diskStorage({
        destination: function (req, file, callback) {
        callback(null, './uploads');
    },
    filename: function (req, file, callback) {
        //  callback(null, file.fieldname + '-' + Date.now());
        callback(null, 'a.jpg');
    }
});

var upload = multer({ storage : storage}).single('userPhoto');
  
router.post('/subir-foto', function(req, res, next) {
    upload(req,res,function(err) {
        if(err) {
            console.log(err);
            return res.end("Error uploading file.");
        }
        res.end("File is uploaded");
    });
});

Código del cliente

Si es una vista integrada en la propia aplicación

<form id        =  "uploadForm"
     enctype   =  "multipart/form-data"
     action    =  "/subir-foto"
     method    =  "post"
>
<input type="file" name="userPhoto" />
<input type="submit" value="Upload Image" name="submit">
</form>

Si es una vista de una aplicación externa (y lo hacemos con Ajax)

<input type="file">
<button id="enviar" >Subir</button>

<script>
    const addFile=(event)=>{
        let archivo = document.querySelector('input');
        const data = archivo.files[0];

        var formData = new FormData();
        formData.append("userPhoto", data);

        fetch('http://localhost:3002/subir-foto',{
            method: 'POST',
            body: formData
        });
    }
    document.querySelector('#enviar').addEventListener('click', addFile);
</script>
Descargar ejemplo

Creando un middleware

Un middleware es un código que se ejecuta antes de procesar la petición. En nuestro caso, vamos a comprobar que el usuario está logueado en cada petición.

Habitualmente se definen en el fichero App.js mediante el método use.

Controlar el acceso de las peticiones a los recursos del servidor mediante un token

El siguiente middleware se ejecutará antes de cada llamada al localsRouter.

app.jsconst privateAccess = require('./middlewares/private-access');

app.use(function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, access-token');

    //Las peticiones de tipo OPTIONS son mandadas automáticamente por el navegador para comprobas cuales son las cabeceras que van a enviarse, por tanto si la petición es de tipo 'OPTIONS', no ejecutaremos más middelwares porque sólo queríamos comprobar las cabeceras. Si no es de tipo OPTIONS, continuamos con el siguiente MIDDLEWARE
    if(req.method === 'OPTIONS') {
        res.send('Success');
    } else {
        next();
    }
});

app.use('/locals', privateAccess, localsRouter);
middlewares/private-access.jsconst verifyToken = require('../servicios/jwt.js');

const getHeader = (req, header) => req.headers[header];

function privateAccess(req, res, next) {
    const token = getHeader(req, 'access-token');

    if (!token) {
        return res.sendStatus(400); // Bad request
    }
    return verifyToken(token, (err, decoded) => {
        if (err) {
            res.sendStatus(403) // forbiden
        }
        // Save user id to request for further usage
        req.userId = decoded.id;
        return next();
    });
}

module.exports = privateAccess;// CommonJs
Enviar datosconst url = 'http://pablomonteserin.com:17041/locals',
    params = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'access-token': 'elToken...'
        },
    };

fetch(url, params)
.then(res => res.json())
.then((data) => {
    if (data === -1) {
        alert('error en el login');
    } else {
        this.setState({ locals: data });
    }
});

Servidor web sin express

Modulo http

Cuando trabajamos con la plataforma Node.js debemos codificar nosotros el servidor web, al contrario de lo que ocurre por ejemplo en PHP en el que tenemos un servidor Apache disponible.

El siguiente código muestra el mensaje "Sitio en desarrollo" para todas las peticiones que se efectuen al puerto 8888 del servidor.

var http=require('http');

var servidor=http.createServer(function(pedido,res){
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<h2>Sitio en desarrollo</h2>');
    res.end();
});

servidor.listen(8888);

console.log('Servidor web iniciado');

Servidor web de páginas estáticas

index.html<a href="pagina1.html">PAGINA 1</a><br>
                <a href="pagina2.html">PAGINA 2</a>
static/pagina1.htmlPAGINA 1
static/pagina2.htmlPAGINA 2
servidor.jsvar http=require('http');
var url=require('url');
var fs=require('fs');

var servidor=http.createServer(function(pedido,respuesta){
    var objetourl = url.parse(pedido.url);
    var camino='static'+objetourl.pathname;
    if (camino=='static/')camino='static/index.html';
    fs.exists(camino,function(existe){
        if (existe) {
            fs.readFile(camino,function(error,contenido){
                if (error) {
                    respuesta.writeHead(500, {'Content-Type': 'text/plain'});
                    respuesta.write('Error interno');
                    respuesta.end();                    
                } else {
                    respuesta.writeHead(200, {'Content-Type': 'text/html'});
                    respuesta.write(contenido);
                    respuesta.end();
                }  
            });
        } else {
            respuesta.writeHead(404, {'Content-Type': 'text/html'});
            respuesta.write('Recurso inexistente');        
            respuesta.end();
        }
    });
});

servidor.listen(8888);

console.log('Servidor web iniciado');

Servidor de cualquier cosa

En el ejemplo anterior sólo servíamos páginas en formato html. Ahora vamos a servir además, imágenes, video, audio, etc.

var http=require('http');
    var url=require('url');
    var fs=require('fs');

    var mime = {
    'html' : 'text/html',
    'css'  : 'text/css',
    'jpg'  : 'image/jpg',
    'ico'  : 'image/x-icon',
    'mp3'  : 'audio/mpeg3',
    'mp4'  : 'video/mp4'
};

var servidor=http.createServer(function(pedido,respuesta){
    var objetourl = url.parse(pedido.url);
    var camino='static'+objetourl.pathname;
    if (camino=='static/')camino='static/index.html';
    fs.exists(camino,function(existe){
        if (existe) {
            fs.readFile(camino,function(error,contenido){
                if (error) {
                    respuesta.writeHead(500, {'Content-Type': 'text/plain'});
                    respuesta.write('Error interno');
                    respuesta.end();                    
                } else {
                    var vec = camino.split('.');
                    var extension=vec[vec.length-1];
                    var mimearchivo=mime[extension];
                    respuesta.writeHead(200, {'Content-Type': mimearchivo});
                    respuesta.write(contenido);
                    respuesta.end();
                }
            });
        } else {
            respuesta.writeHead(404, {'Content-Type': 'text/html'});
            respuesta.write('Recurso inexistente');        
            respuesta.end();
        }
    });
});

servidor.listen(8888);

console.log('Servidor web iniciado');

Creación de una caché en el servidor

var http=require('http');
    var url=require('url');
    var fs=require('fs');

    var mime = {
    'html' : 'text/html',
    'css'  : 'text/css',
    'jpg'  : 'image/jpg',
    'ico'  : 'image/x-icon',
    'mp3'  : 'audio/mpeg3',
    'mp4'  : 'video/mp4'
};

var cache={};

var servidor=http.createServer(function(pedido,respuesta){
    var objetourl = url.parse(pedido.url);
    var camino='static'+objetourl.pathname;
    if (camino=='static/')camino='static/index.html';
    if (cache[camino]) {
        var vec = camino.split('.');
        var extension=vec[vec.length-1];
        var mimearchivo=mime[extension];
        respuesta.writeHead(200, {'Content-Type': mimearchivo});
        respuesta.write(cache[camino]);
        respuesta.end();
        console.log('Recurso recuperado del cache:'+camino);               
    } else {
        fs.exists(camino,function(existe){
            if (existe) {
                fs.readFile(camino,function(error,contenido){
                    if (error) {
                        respuesta.writeHead(500, {'Content-Type': 'text/plain'});
                        respuesta.write('Error interno');
                        respuesta.end();                    
                    } else {
                        cache[camino]=contenido;
                        var vec = camino.split('.');
                        var extension=vec[vec.length-1];
                        var mimearchivo=mime[extension];
                        respuesta.writeHead(200, {'Content-Type': mimearchivo});
                        respuesta.write(contenido);
                        respuesta.end();
                        console.log('Recurso leido del disco:'+camino);
                    }
                });
            } else {
                respuesta.writeHead(404, {'Content-Type': 'text/html'});
                respuesta.write('Recurso inexistente');        
                respuesta.end();
            }
        });
    }
});

servidor.listen(8888);

console.log('Servidor web iniciado');

Recuperación de datos por POST

var http=require('http');
    var url=require('url');
    var fs=require('fs');
    var querystring = require('querystring');

    var mime = {
    'html' : 'text/html',
    'css'  : 'text/css',
    'jpg'  : 'image/jpg',
    'ico'  : 'image/x-icon',
    'mp3'  :    'audio/mpeg3',
    'mp4'  : 'video/mp4'
};

var servidor=http.createServer(function(pedido,respuesta){
    var objetourl = url.parse(pedido.url);
    var camino='public'+objetourl.pathname;
    if (camino=='public/')camino='public/index.html';
    encaminar(pedido,respuesta,camino);
});

servidor.listen(8888);


function encaminar (pedido,respuesta,camino) {
    switch (camino) {
        case 'public/recuperardatos': {
            recuperar(pedido,respuesta);
            break;
        }    
        default : {  
            fs.exists(camino,function(existe){
                if (existe) {
                    fs.readFile(camino,function(error,contenido){
                        if (error) {
                            respuesta.writeHead(500, {'Content-Type': 'text/plain'});
                            respuesta.write('Error interno');
                            respuesta.end();                    
                        } else {
                            var vec = camino.split('.');
                            var extension=vec[vec.length-1];
                            var mimearchivo=mime[extension];
                            respuesta.writeHead(200, {'Content-Type': mimearchivo});
                            respuesta.write(contenido);
                            respuesta.end();
                        }
                    });
                } else {
                    respuesta.writeHead(404, {'Content-Type': 'text/html'});
                    respuesta.write('Recurso inexistente');        
                    respuesta.end();
                }
            });    
        }
    }    
}


function recuperar(pedido,respuesta) {
    var info = '';
    pedido.on('data', function(datosparciales){
        info += datosparciales;
    });
    pedido.on('end', function(){
        var formulario = querystring.parse(info);
        respuesta.writeHead(200, {'Content-Type': 'text/html'});
        var pagina='Nombre de usuario:'+formulario['nombre']+'<br>'+
        'Clave:'+formulario['clave'];
        respuesta.end(pagina);
    });    
}

console.log('Servidor web iniciado');

Creación de un chat usando sockets sin express

npm init
npm i socket.io
npm i express
index.html
        <ul id="messages"></ul>
        <form action="">
        <input id="m" autocomplete="off" /><button>Send</button>
        </form>
        <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
        <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
        <script>
        $(function () {
        var socket = io();
        //Este código se ejecuta cada vez que mando un mensaje
        $('form').submit(function(){
        console.log("yo mando un mensaje");
        socket.emit('mensaje', $('#m').val());
        return false;
    });

    //Este código se ejecuta cada vez que alguien manda un mensaje
    socket.on('mensaje', function(msg){
    console.log("alguien manda un mensaje")
    $('#messages').append($('<li>').text(msg));
});
});
</script>
index.jsvar app = require('express')();
    // Creamos nuestro servidor de aplicaciones http
    var http = require('http').Server(app);
    // Creamos nuestro servidor de websockets para ejecutar en el servidor anterior
    var io = require('socket.io')(http);
    //Escucharemos el puerto 3000
    var port = process.env.PORT || 3000;

    app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

//Detectamos cuando un nuevo usuario se conecta
io.on('connection', function(socket){
//El siguiente código es lanzado cada vez que alguien lanza un mensaje
socket.on('mensaje', function(msg){
//Recogemos el evento de mandar un mensaje en el cliente
io.emit('mensaje', msg);
});
});

http.listen(port, function(){
console.log('listening on *:' + port);
});

Publicar un plugin en npm

  1. Creamos un nuevo proyecto
    npm init
  2. Creamos nuestro usuario
    npm adduser
  3. Verificamos nuestra cuenta
  4. Publicamos:
    npm publish

Chokidar

npm i chokidar
npm init
npm i chokidar
icono de mandar un mailPreguntame lo que quieras!
Pablo Monteserín
contacta conmigoPablo Monteserín

El servicio de resolución de dudas técnicas es sólo para los usuarios premium. Si tienes cualquier otra duda, usa el formulario de contacto. ¡Gracias!