Este tutorial pretende mostrar como funciona la herramienta Slush, para hacer scaffolding con Javascript. En él veremos como instalarlo y como hacer un primer generador sencillo para una aplicación de ejemplo. También se compara a nivel general con Yeoman, la herramienta más importante de este tipo.
Índice de contenidos
- 1. Introducción
- 2. Entorno
- 3. Instalación
- 4. Funcionamiento
- 5. El slushfile
- 6. Creación de un generador
- 7. Repositorio de generadores
- 8. Conclusiones
- 9. Referencias
1. Introducción
En el arranque de proyectos Javascript, en aplicaciones empresariales donde se quiere que las aplicaciones sigan siempre un mismo patrón es conveniente utilizar herramientas de scaffolding.
La traducción literal de scaffolding es “andamiaje”, es decir, la creación de los “cimientos” a partir del esqueleto o el arquetipo. El arquetipo es un punto de partida del modelo original de una aplicación para el resto de aplicaciones. Por ejemplo, análogamente en Java tendríamos maven-archetype.
Además de Slush existen otras herramientas para hacer scaffolding, como Yeoman, CodeKit, Lineman y Fireshell. De todas estas la herramienta más extendida es Yeoman (Tutorial «Creación de un generador de Yeoman»).
Yeoman (2012) en sus inicios utilizaba Grunt como gestor de tareas, aunque en las últimas versiones ya utiliza Gulp en al menos algunos módulos, que es más eficiente. Slush está concebido desde su creación como una herramienta basada en Gulp, y aunque es algo más reciente (2014) llama la atención su sencillez de uso.
Para utilizar esta herramienta es necesario tener instalado Node.js y Gulp. Para poder comprender este tutorial se necesita como requisito al menos unas nociones de cómo funciona Gulp y como se definen y ejecutan tareas (Tutorial «Primeros pasos con Gulp».).
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil Mac Book Pro 15″ (2,3 Ghz Intel Core i7, 16 GB DDR3)
- Sistema Operativo: Mac OS X El Capitan
- NodeJS v4.4.3
- npm 3.8.6
- Atom 1.7.1
- Gulp 3.9.0
3. Funcionamiento
Las principales características de un generador son:
- Copiar una estructura de proyecto (con los directorios y todo lo demás).
- Preguntar al usuario para algunas opciones del proyecto.
- Reemplazar variables en las plantillas (archivos del proyecto) en función de las respuestas introducidas por el usuario.
- Auto-instalación de dependencias necesarias para el proyecto generado.
- Solicitar que ficheros se desea sobrescribir (cuando se ejecuta el generador por segunda vez).
Todo esto se podría hacer fácilmente utilizando Gulp directamente, es decir, utilizar Gulp como un generador. Para que fuera más fácil de usar un generador de un proyecto realizado con Gulp se construyó Slush.
Slush localiza todos los proyectos generadores construidos con Gulp, lo que se denominan “slush generators” y hace posible ejecutar un generador sin la necesidad de especificar su ubicación.
4. Instalación
En primer lugar debemos instalar NVM (Node Version Manager) para tener la flexibilidad de cambiar de versión Node.Js en cualquier momento. Instalamos la última versión y asegurarnos la activación de las variables de entorno.
> curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash > nvm install stable > nvm alias default stable
A continuación instalamos Gulp de manera global
> npm install --global gulp-cli
Después debemos instalar Slush
> npm i -g gulp slush slush-generator
5. El slushfile
Slush no viene con ninguna funcionalidad propia, lo único que ofrece es una convención y conveniencia de ejecutar gulpfiles globales. Estos gulpfiles de los generadores se denominan slushfiles. El propósito de un slushfile es realizar tareas de scaffolding del proyecto o cualquier utilidad para el mismo. Si no disponemos de alguna funcionalidad probablemente se podría incorporar utilizando un plugin de Gulp.
Como se puede ver a continuación se dispone de una lista de prompt donde se muestran las preguntas que se le va a hacer al usuario y la variable donde se va a almacenar el resultado. Para ello se utiliza el plugin inquirer. Esta lista se podría modificar para añadir más parámetros del proyecto. Por defecto además se utilizan los plugins gulp-install, gulp-conflict, gulp-template y gulp-rename.
6. Creación de un generador
En primer lugar debemos de crear un directorio para el proyecto y dentro crear un módulo de node de la siguiente manera.
> mkdir > cd > slush generator
A continuación Slush nos pedirá una serie de preguntas sobre parámetros de nuestra aplicación.
Si abrimos el proyecto en un editor veremos la estructura del generador que hemos creado.
Los elementos principales son:
- package.json: fichero con el nombre del generador, las dependencias del proyecto, etc
- slushfile.js: fichero con las tareas relativas al generador
- templates: directorio con todos los ficheros y directorios que se copiaran en un nuevo proyecto, incluyendo un package.json, un gulpfile.js, los fuentes javascript, test unitarios, css, imágenes, etc.
Para nuestro ejemplo vamos a añadir en el directorio templates una estructura básica de un proyecto de ejemplo, que contendrá los siguientes ficheros: gulpfile.js, package.json, index.html, app.js, app.css y una imagen.
package.json
{ "name": "", "version": "1.0.0", "devDependencies": { "gulp-connect": "^2.0.6", "gulp": "^3.8.6" } }
gulpfile.js
var gulp = require('gulp'), connect = require('gulp-connect'); gulp.task('connect', function() { connect.server({ root: './src', livereload: true }); }); gulp.task('html', function() { gulp.src('src/index.html') .pipe(connect.reload()); }); gulp.task('watch', function() { gulp.watch(['src/*.html', 'src/css/**', 'src/js/**'], ['html']); }); gulp.task('default', ['connect', 'watch']);
index.html
<!DOCTYPE html> <html> <head> <title><%= appName %></title> <link rel='stylesheet' href='css/app.css' /> </head> <body> <h1><%= appName %></h1> <h1>Welcome to <%= appName %></h1><br> <h2><%= appDescription %></h2><br> <h3>Made by <%= authorName %></h3> <script type="text/javascript" src="js/app.js"></script> </body> </html>
app.css
body { padding: 50px; background-image: url("../img/smoke.jpg"); color: yellow; }
Para probar el generador de manera local debemos ejecutar el siguiente comando en el directorio raíz para crear un enlace simbólico a nuestro generador.
> sudo npm link
Si estuviéramos trabajando con un repositorio público (https://npmjs.com) o privado (por ejemplo Nexus) de Node podríamos publicarlo mediante npm publish. Para el alcance de este tutorial lo haremos simplemente con npm link.
A continuación vamos a crear un proyecto nuevo a partir del generador. Para ello nos situaremos fuera del generador y crearemos un directorio para el proyecto y lo ejecutaremos de la siguiente manera:
> mkdir app-demo-1 > cd app-demo-1 > slush app-demo-generator
Para arrancar la aplicación bastaría con hacer un gulp, abrir una pestaña del navegador con la url http://localhost:8080 y … vualá.
Una parte interesante de Slush es que se podrían hacer generadores para determinadas partes de una aplicación es decir, sub-generadores. Por ejemplo, imaginemos creamos un generador para nuestra aplicación con AngularJs, Jasmine, etc. y ya hemos creado nuestro “esqueleto”. Hasta ahí bien, quizás hemos creado un una vista, un controlador y un test para un componente, pero ¿qué pasa cuando queremos crear más componentes (módulos) que forman parte de la aplicación, pero que tienen siempre la misma estructura?
Pues en este caso podríamos crear un sub-generador que creará un directorio con un controlador, una vista, test, directivas, etc. para la entidad que estemos generando y parametrizando el nombre de la entidad que le dará nombre a los ficheros, variables, etc.
Al realizar el ejemplo me encontré con un bug (https://github.com/slushjs/slush/issues/46) por el cual la imagen copiada al nuevo proyecto estaba corrupta. En la web viene como solucionarlo hasta que lo incluyan en la próxima release.
7. Repositorio de generadores
Slush dispone de varios generadores desarrollados con diferentes tecnologías que podrían adaptarse a las necesidades de nuestro proyecto. Por ejemplo, podríamos crear un proyecto con tecnologías como AngularJs, ReactJs, Backbone, o proyectos con frontend y backend en javascript con ExpressJs y MongoDb, etc.
A fecha de este tutorial la web de Slush (http://slushjs.github.io/generators/#/) ofrece 310 generadores, que son pocos si los comparamos con Yeoman (http://yeoman.io/generators/), que tiene 3764 generadores. En este aspecto Yeoman ofrece un repertorio mucho más amplio, aunque también hay que tener en cuenta que Slush es mucho más reciente.
8. Conclusiones
La herramienta de scaffolding más extendida en Javascript sigue siendo Yeoman, aunque Slush es una alternativa muy interesante. En la web de Slush dice que pretende ser un reemplazo de Yeoman, aunque a día de hoy esto no es cierto. Lo relevante de Slush es que tiene un gran potencial si lo siguen evolucionando, pero a día de hoy Yeoman sigue siendo la herramienta predominante. Se deja a criterio de cada uno elegir la herramienta que más le convenga utilizar en su proyecto.
Una de las ventajas de Slush es que está basado en Gulp, que se basa en el enfoque de código sobre configuración, lo cual hace que el scaffolding sea pueda hacer de una manera más sencilla. Si se realiza scaffolding mediante configuración requiere más conocimiento sobre la implementación específica además de documentación. En cambio si se realiza por código es mucho más explícito, generalmente mucho menor cantidad de líneas y requiere menos conocimiento del dominio.
Un inconveniente de Slush es que es quizás muy reciente en comparación con Yeoman y no está tan maduro. A pesar de que tiene un buen número de generadores realizados por terceros, y de que es bastante fácil de hacer uno propio, Yeoman tiene un número mucho mayor de generadores disponibles, además de mayor cantidad de documentación en la red.
9. Referencias
- http://slushjs.github.io/#/
- http://yeoman.io/
- https://scotch.io/tutorials/easy-project-scaffolding-with-gulp-and-slush
- http://www.slant.co/topics/1485/compare/~yeoman_vs_codekit_vs_slush
- http://www.rae.es/
- https://adictosaltrabajo.com/tutoriales/creacion-de-un-generador-de-yeoman
- http://joakim.beng.se/blog/posts/slush-replacing-yeoman-with-gulp.html
- http://thejackalofjavascript.com/building-slush-generator/
Hola, me está dando este error al generar el proyecto usando ya la plantilla:
events.js:141
throw er; // Unhandled ‘error’ event
^
SyntaxError: Unexpected token ILLEGAL
at Function (native)
at template (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/node_modules/lodash/dist/lodash.js:6306:22)
at Transform._transform (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/index.js:19:31)
at Transform._read (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/node_modules/readable-stream/lib/_stream_transform.js:184:10)
at Transform._write (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/node_modules/readable-stream/lib/_stream_transform.js:172:12)
at doWrite (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/node_modules/readable-stream/lib/_stream_writable.js:237:10)
at writeOrBuffer (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/node_modules/readable-stream/lib/_stream_writable.js:227:5)
at Transform.Writable.write (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/gulp-template/node_modules/readable-stream/lib/_stream_writable.js:194:11)
at write (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_readable.js:623:24)
at flow (/home/diego/workspace/Laboratorios/Javascript/HolaMundo_Slush_CreateGenerator/HolaMundo_Generator/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_readable.js:632:7)