yeoman tutorial

Hoy vamos con un tutorial de Yeoman para crear un generador de servidor Express adaptado a nuestras necesidades. Para los que no lo sepais, Yeoman es un generador de codigo que nos ayuda a acelerar el proceso de creacion de proyectos

Esta herramienta se puede extender creando generadores propios o usando los generadores que aporta la comunidad. Hoy vamos a crear un generador propio en 10 minutos

Yeoman tutorial

Lo primero es instalar Yeoman en el sistema

npm install -g yo bower grunt-cli gulp

Es necesario instalar tambien Bower, Grunt y Gulp

Una vez instalado todo podemos comenzar a crear nuestro generador. Lo primero es crear el fichero package.json

{
  "name": "generator-rubenjgarcia-express",
  "version": "0.1.0",
  "description": "Express Generator",
  "files": [
    "app"
  ],
  "author": "Ruben J Garcia"
}

El nombre tiene que empezar por generator para poder usarlo con Yeoman. Lo siguiente que haremos es instalar la dependencia de la libreria de yeoman-generator

npm install --save yeoman-generator

Vamos a crear nuestro generador principal. Debe estar en el directorio app en el fichero index.js

'use strict';

var generators = require('yeoman-generator');

module.exports = generators.Base.extend({
    helloworld: function () {
        console.log('Hello World!');
    }
});

Con este codigo ya podremos ejecutar nuestro generador. Usando el comando npm link y luego yo rubenjgarcia-express veremos un mensaje en consola como este

Hello World!

Ya tenemos todo configurado y listo para poder continuar. Lo que vamos a hacer es sacar una lista de opciones al usuario para que elija que tipo de servidor quiere, si solo quiere que sea REST con json o que sea un servidor web con capacidad para servir paginas dinamicas, ademas de configurar el puerto, nombre de la aplicacion y si queremos deshabilitar la cabecera X-Powered-By (algo muy recomendable por temas de seguridad)

'use strict';

var generators = require('yeoman-generator');
var slugify = require('underscore.string/slugify');

module.exports = generators.Base.extend({
    constructor: function () {
        generators.Base.apply(this, arguments);

        //Hacemos que la funcion slugify pueda ser usada en nuestros templates
        this.slugify = slugify;
    },
    prompting: {
        //Recogemos todas las opciones
        appName: function () {
            var done = this.async();
            this.prompt({
                type: 'input',
                name: 'appName',
                message: 'What is your app name',
                default: 'My Express App'
            }, function (response) {
                this.options.appName = response.appName;
                done();
            }.bind(this));
        },
        type: function () {
            var done = this.async();
            this.prompt({
                type: 'list',
                name: 'type',
                message: 'What Express type do you want to create',
                choices: [
                    {
                        name: 'REST',
                        value: 'rest'
                    },
                    {
                        name: 'Web',
                        value: 'web'
                    }
                ],
                default: 'rest'
            }, function (response) {
                this.options.type = response.type;
                done();
            }.bind(this));
        },
        disableHeader: function () {
            var done = this.async();
            this.prompt({
                type: 'confirm',
                name: 'disableHeader',
                message: 'Disable X-Powered-by header',
                default: true
            }, function (response) {
                this.options.disableHeader = response.disableHeader;
                done();
            }.bind(this));
        },
        port: function () {
            var done = this.async();
            this.prompt({
                type: 'input',
                name: 'port',
                message: 'What port do you want to listen',
                default: 3000,
                validate: function(input) {

                    var done = this.async();

                    setTimeout(function() {
                        if (isNaN(input) || input <= 1024 || input > 65535) {
                            done("You need to provide a number between 1024 and 65535");
                            return;
                        }

                        done(true);
                    }, 0);
                }
            }, function (response) {
                this.options.port = response.port;
                done();
            }.bind(this));
        }
    },
    writing: function () {
        var done = this.async();
        
        //De momento solo construimos si es de tipo REST
        if (this.options.type === 'web') {
            console.error('Not implemented yet');
            done();
        }

        //Generamos los archivos
        this.template('server.js');
        this.template('package.json');
        this.template('gulpfile.js');
        done();
    },
    install: function () {
        //Instalamos las dependencias
        this.installDependencies({bower: false});
    }
});

La parte donde se pregunta al usuario las opciones es en el prompting. Si quereis mas informacion sobre como generar las preguntas y los tipos de respuestas que pueden usarse mirad la documentacion de Inquirer

Una vez hecho esto solo queda crear nuestras plantillas. Las plantillas estan basadas en EJS asi que para mas informacion podeis mirar su documentacion. Estas plantillas deben de estar dentro de la carpeta app/templates. Veamos la del servidor: server.js

var logger = require('morgan');
var bodyParser = require('body-parser');
var express = require('express');

var app = express();
<% if (options.disableHeader) { %>
app.disable('x-powered-by');<% } %>
app.use(bodyParser.json());
app.use(logger('dev'));

app.post('/', function (req, res) {
    res.end();
});

app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

app.use(function (err, req, res, next) {
    res.status(err.status || 500);
    if (res.statusCode >= 500 && err.stack) {
        console.log(err.stack);
    }

    res.end();
});

app.set('port', process.env.PORT || <%= options.port %>);

var server = app.listen(<%= options.port %>, function () {
    console.log('Server listening at http://%s:%s', server.address().address, server.address().port)
});

Una vez creadas las plantillas ya tenemos todo lo necesario para que funcione nuestro generador. Creamos un directorio nuevo donde vayamos a generar el codigo fuente de nuestro servidor y ejecutamos yo rubenjgarcia-express y veremos algo asi

? What is your app name My Express App
? What Express type do you want to create REST
? Disable X-Powered-by header Yes
? What port do you want to listen 3000
create package.json
create server.js
create gulpfile.js


I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.

Esto deja todo el codigo generado y las dependencias instaladas y listo para su ejecucion. Como hemos creado un fichero Gulp podemos ejecutar nuestro servidor con el comando gulp que ademas estara monitorizando los cambios en el codigo fuente y reiniciara automaticamente el despliegue

Podeis descargar el codigo de este proyecto en el repositorio de Github

Comparte este articuloShare on Facebook
Facebook
Share on Google+
Google+
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin

Comentarios

comentarios