Para quien no lo sepa con estos generadores nos van a realizar las tareas como la de crear estructuras, compilar automáticamente sass y lees, optimizar imágenes, crear diferentes entonos, realizar test y largo etc.. vamos cualquier tarea que sea repetitiva, además de refrescar automáticamente tu navegador gracias al Livereload, lo mas complicado entre comillas es hacer una buena configuración para ellos, claro con estos gestores tan frontales no vamos a poder ejecutar código PHP, sin antes configurarlo como veremos después.
Empecemos por el principio:
Yeoman
Es un generador que hace uso de Bower y Grunt, su dos grandes aliados. Yeoman tiene una gran lista de generador para que construya una gran base por nosotros.Bower
Nos sirve para el manejo de las dependencias de nuestros proyectos, se ejecuta desde la línea de comandos y su configuración se crea en un archivo llamado bower.json luego desde el terminal ejecutaremos sus comandos y tendremos descargados los paquetes que hayamos elegido en nuestro local.Grunt
Es una herramienta para automatizar acciones o procesos, como minimizar css y js, compilar less o sass, ejecución de pruebas, construcción y otra infinidad de tareas, se configura através de dos archivos Packaged.json (donde listaremos las dependencias) y Grunt.js (donde crearemos la configuración), existe un gran numero de plugins en su repositorio puedes encontrar de todo tipo de acciones que se pueden ajustar a diferentes necesidades.PHP
Que voy a contar de PHP que no sepas…Un poco de diversión comenzaremos con las instalaciones:
Antes de nada decirte que ahora mismo solo lo puedes hacer en Linux y Mac, tal vez algún dia lo tenga para el Windows pero no mola nada, mucho mejor te va a funcionar en un linux, así que seamos profesionales y utilicemos sistemas profesionales, tienes que tener instalado previamente Node.js y Ruby.
Aquí unos links para que te sirvan de ayuda:
https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-on-centos-6-with-rvm
http://www.nodeclipse.org/2013/08/30/Node.js-installation-on-CentOS-Linux.html
http://codybonney.com/installing-node-js-0-10-24-on-centos-6-4/
La siguiente te instalara Yoeman Grunt y Bower, PHP doy por hecho que ya lo tienes instalado, además de que estas utilizando un usuario con privilegios para hacer las instalaciones:
$ npm install -g yo grunt-cli bower
Ahora una vez instalado nuestros generadores, lo suyo es utilizar un usuario de linux que sea normal que vamos a utilizar para nuestro proyecto y no sea root, con la siguiente instrucción veremos un listado y elegiremos un generador para así crearemos un nuevo proyecto web, se puede usar otros comandos para hacer uso de otros generadores mas específicos de Yeoman.
$ yo
mostrara los siguente:
? 'Allo! What would you like to do?
Update your generators
Install a generator
Find some help
--------------
Run a generator
Polymer
Angular ? Update Available!
? Bootstrap Less
Karma
Php
Nosotros ahora vamos elegir el de Boostrap Less por que es la que me resulta mas operativa para configurar ese proyecto para hacer funcionar Grunt y PHP a la vez.
Hacer esta elección para configurar Grunt y PHP nos va a producir una salida por consola similar a esta:
? 'Allo! What would you like to do? Bootstrap Less
Make sure you are in the directory you want to scaffold into.
This generator can also be run with: yo bootstrap-less
_-----_
| | .--------------------------.
|--(o)--| | Welcome to Yeoman, |
`---------´ | ladies and gentlemen! |
( _´U`_ ) '--------------------------'
/___A___\
| ~ |
__'.___.'__
´ ` |° ´ Y `
Out of the box I include HTML5 Boilerplate, Bootstrap with less, and a Gruntfile.js to build your app.
? What more would you like? Bootstrap Javascript files, FontAwesome
create Gruntfile.js
create package.json
conflict .gitignore
? Overwrite .gitignore? overwrite
force .gitignore
create .gitattributes
conflict .bowerrc
? Overwrite .bowerrc? overwrite
force .bowerrc
create bower.json
conflict .jshintrc
? Overwrite .jshintrc? overwrite
force .jshintrc
conflict .editorconfig
? Overwrite .editorconfig? overwrite
force .editorconfig
create app/favicon.ico
create app/404.html
create app/robots.txt
create app/.htaccess
create app/styles/main.less
create app/index.html
create app/scripts/hello.coffee
create app/scripts/main.js
invoke mocha
I'm all done. Running bower install & npm install for you to install the required dependencies. If this fails, try running the command yourself.
create test/bower.json
create test/.bowerrc
create test/spec/test.js
create test/index.html
bower modernizr#~2.6.2 cached git://github.com/Modernizr/Modernizr.git#2.6.3
bower modernizr#~2.6.2 validate 2.6.3 against git://github.com/Modernizr/Modernizr.git#~2.6.2
bower chai#~1.8.0 cached git://github.com/chaijs/chai.git#1.8.1
bower chai#~1.8.0 validate 1.8.1 against git://github.com/chaijs/chai.git#~1.8.0
bower jquery#~1.9.1 cached git://github.com/jquery/jquery.git#1.9.1
bower jquery#~1.9.1 validate 1.9.1 against git://github.com/jquery/jquery.git#~1.9.1
bower mocha#~1.14.0 cached git://github.com/visionmedia/mocha.git#1.14.0
bower mocha#~1.14.0 validate 1.14.0 against git://github.com/visionmedia/mocha.git#~1.14.0
bower bootstrap#~3.0.0 cached git://github.com/twbs/bootstrap.git#3.0.3
bower bootstrap#~3.0.0 validate 3.0.3 against git://github.com/twbs/bootstrap.git#~3.0.0
bower font-awesome#~4.0.0 cached git://github.com/FortAwesome/Font-Awesome.git#4.0.3
bower font-awesome#~4.0.0 validate 4.0.3 against git://github.com/FortAwesome/Font-Awesome.git#~4.0.0
bower chai#~1.8.0 install chai#1.8.1
bower mocha#~1.14.0 install mocha#1.14.0
chai#1.8.1 bower_components/chai
mocha#1.14.0 bower_components/mocha
bower modernizr#~2.6.2 install modernizr#2.6.3
bower font-awesome#~4.0.0 install font-awesome#4.0.3
bower jquery#~1.9.1 install jquery#1.9.1
bower bootstrap#~3.0.0 install bootstrap#3.0.3
modernizr#2.6.3 app/bower_components/modernizr
font-awesome#4.0.3 app/bower_components/font-awesome
jquery#1.9.1 app/bower_components/jquery
bootstrap#3.0.3 app/bower_components/bootstrap
+-- jquery#1.9.1
npm WARN package.json grunt/php@0.0.0 No description
npm WARN package.json grunt/php@0.0.0 No repository field.
npm WARN package.json grunt/php@0.0.0 No README data
/
> phantomjs@1.9.12 install /var/www/html/grunt/php/node_modules/grunt-mocha/node_modules/grunt-lib-phantomjs/node_modules/phantomjs
> node install.js
Download already available at /tmp/phantomjs/phantomjs-1.9.8-linux-x86_64.tar.bz2
Extracting tar contents (via spawned process)
Removing /var/www/html/grunt/php/node_modules/grunt-mocha/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/lib/phantom
Copying extracted folder /tmp/phantomjs/phantomjs-1.9.8-linux-x86_64.tar.bz2-extract-1416474106615/phantomjs-1.9.8-linux-x86_64 -> /var/www/html/grunt/php/node_modules/grunt-mocha/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/lib/phantom
Removing /tmp/phantomjs/phantomjs-1.9.8-linux-x86_64.tar.bz2-extract-1416474106615
Writing location.js file
Done. Phantomjs binary available at /var/www/html/grunt/php/node_modules/grunt-mocha/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/lib/phantom/bin/phantomjs
> pngquant-bin@1.0.1 postinstall /var/www/html/grunt/php/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-pngquant/node_modules/pngquant-bin
> node lib/install.js
fetch : https://raw.github.com/imagemin/pngquant-bin/v1.0.1/vendor/linux/x64/pngquant
progress : [====================] 100% 0.0s
? pre-build test failed, compiling from source...
? pngquant failed to build, make sure that libpng-dev is installed
{ [Error: Command failed: make: *** No hay ninguna regla para construir el objetivo `config.mk', necesario para `lib/libimagequant.a'. Alto.
] killed: false, code: 2, signal: null }
> jpegtran-bin@1.0.2 postinstall /var/www/html/grunt/php/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-jpegtran/node_modules/jpegtran-bin
> node lib/install.js
fetch : https://raw.github.com/imagemin/jpegtran-bin/v1.0.2/vendor/linux/x64/jpegtran
progress : [====================] 100% 0.0s
? pre-build test passed successfully!
> gifsicle@1.0.3 postinstall /var/www/html/grunt/php/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle
> node lib/install.js
fetch : https://raw.github.com/imagemin/gifsicle-bin/v1.0.3/vendor/linux/x64/gifsicle
progress : [====================] 100% 0.0s
? pre-build test passed successfully!
> optipng-bin@1.0.1 postinstall /var/www/html/grunt/php/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-optipng/node_modules/optipng-bin
> node lib/install.js
fetch : https://raw.github.com/imagemin/optipng-bin/v1.0.1/vendor/linux/x64/optipng
progress : [====================] 100% 0.0s
? pre-build test failed, compiling from source...
? optipng built successfully!
grunt-rev@0.1.0 ../node_modules/grunt-rev
grunt-contrib-clean@0.6.0 ../node_modules/grunt-contrib-clean
+-- rimraf@2.2.8
grunt-concurrent@1.0.0 ../node_modules/grunt-concurrent
+-- pad-stdio@1.0.0 (lpad@1.0.0)
+-- async@0.9.0
time-grunt@1.0.0 ../node_modules/time-grunt
+-- date-time@1.0.0
+-- figures@1.3.5
+-- text-table@0.2.0
+-- pretty-ms@1.0.0 (parse-ms@1.0.0, get-stdin@3.0.0)
+-- hooker@0.2.3
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
grunt-contrib-copy@0.6.0 ../node_modules/grunt-contrib-copy
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
jshint-stylish@1.0.0 ../node_modules/jshint-stylish
+-- log-symbols@1.0.1
+-- text-table@0.2.0
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
+-- string-length@1.0.0 (strip-ansi@2.0.0)
grunt-contrib-concat@0.5.0 ../node_modules/grunt-contrib-concat
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
+-- source-map@0.1.40 (amdefine@0.1.0)
grunt-contrib-coffee@0.11.1 ../node_modules/grunt-contrib-coffee
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
+-- coffee-script@1.7.1 (mkdirp@0.3.5)
+-- lodash@2.4.1
grunt-contrib-watch@0.6.1 ../node_modules/grunt-contrib-watch
+-- async@0.2.10
+-- tiny-lr-fork@0.0.5 (debug@0.7.4, faye-websocket@0.4.4, noptify@0.0.3, qs@0.5.6)
+-- gaze@0.5.1 (globule@0.1.0)
+-- lodash@2.4.1
grunt-usemin@2.4.0 ../node_modules/grunt-usemin
+-- debug@1.0.4 (ms@0.6.2)
+-- lodash@2.4.1
load-grunt-tasks@0.6.0 ../node_modules/load-grunt-tasks
+-- multimatch@0.3.0 (array-differ@0.1.0, array-union@0.1.0, minimatch@0.3.0)
+-- findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
matchdep@0.3.0 ../node_modules/matchdep
+-- stack-trace@0.0.7
+-- resolve@0.5.1
+-- globule@0.1.0 (minimatch@0.2.14, glob@3.1.21, lodash@1.0.1)
+-- findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
grunt-contrib-htmlmin@0.3.0 ../node_modules/grunt-contrib-htmlmin
+-- pretty-bytes@0.1.2
+-- chalk@0.4.0 (has-color@0.1.7, ansi-styles@1.0.0, strip-ansi@0.1.1)
+-- html-minifier@0.6.9 (change-case@2.1.5, relateurl@0.2.5, clean-css@2.2.18, cli@0.6.5, uglify-js@2.4.15)
grunt-contrib-connect@0.8.0 ../node_modules/grunt-contrib-connect
+-- connect-livereload@0.4.1
+-- open@0.0.5
+-- async@0.9.0
+-- portscanner@0.2.3 (async@0.1.15)
+-- connect@2.19.6 (parseurl@1.0.1, response-time@2.0.0, escape-html@1.0.1, pause@0.0.1, cookie-signature@1.0.3, cookie@0.1.2, vhost@1.0.0, fresh@0.2.2, qs@0.6.6, basic-auth-connect@1.0.0, on-headers@0.0.0, bytes@1.0.0, morgan@1.1.1, serve-favicon@2.0.1, errorhandler@1.0.2, cookie-parser@1.1.0, connect-timeout@1.1.0, body-parser@1.3.1, method-override@2.0.2, debug@1.0.2, express-session@1.2.1, csurf@1.2.1, type-is@1.2.1, compression@1.0.7, serve-static@1.2.3, multiparty@3.2.8, serve-index@1.1.1)
grunt@0.4.5 ../node_modules/grunt
+-- dateformat@1.0.2-1.2.3
+-- which@1.0.5
+-- eventemitter2@0.4.14
+-- getobject@0.1.0
+-- rimraf@2.2.8
+-- colors@0.6.2
+-- async@0.1.22
+-- grunt-legacy-util@0.2.0
+-- hooker@0.2.3
+-- nopt@1.0.10 (abbrev@1.0.5)
+-- exit@0.1.2
+-- minimatch@0.2.14 (sigmund@1.0.0, lru-cache@2.5.0)
+-- glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
+-- lodash@0.9.2
+-- coffee-script@1.3.3
+-- underscore.string@2.2.1
+-- iconv-lite@0.2.11
+-- findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
+-- grunt-legacy-log@0.1.1 (underscore.string@2.3.3, lodash@2.4.1)
+-- js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.15)
grunt-svgmin@1.0.0 ../node_modules/grunt-svgmin
+-- log-symbols@1.0.1
+-- pretty-bytes@1.0.1 (get-stdin@1.0.0)
+-- each-async@1.1.0 (onetime@1.0.0, setimmediate@1.0.2)
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
+-- svgo@0.4.5 (colors@0.6.2, whet.extend@0.9.9, coa@0.4.1, sax@0.6.1, js-yaml@2.1.3)
grunt-contrib-uglify@0.6.0 ../node_modules/grunt-contrib-uglify
+-- uri-path@0.0.2
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
+-- uglify-js@2.4.15 (uglify-to-browserify@1.0.2, async@0.2.10, optimist@0.3.7, source-map@0.1.34)
+-- lodash@2.4.1
+-- maxmin@1.0.0 (figures@1.3.5, pretty-bytes@1.0.1, gzip-size@1.0.0)
grunt-contrib-cssmin@0.10.0 ../node_modules/grunt-contrib-cssmin
+-- chalk@0.4.0 (has-color@0.1.7, ansi-styles@1.0.0, strip-ansi@0.1.1)
+-- clean-css@2.2.18 (commander@2.2.0)
+-- maxmin@0.2.2 (figures@1.3.5, pretty-bytes@0.1.2, chalk@0.5.1, gzip-size@0.2.0)
grunt-contrib-jshint@0.10.0 ../node_modules/grunt-contrib-jshint
+-- hooker@0.2.3
+-- jshint@2.5.10 (strip-json-comments@1.0.2, underscore@1.6.0, exit@0.1.2, minimatch@1.0.0, console-browserify@1.1.0, shelljs@0.3.0, cli@0.6.5, htmlparser2@3.8.2)
grunt-mocha@0.4.11 ../node_modules/grunt-mocha
+-- lodash@2.3.0
+-- mocha@1.18.2 (diff@1.0.7, growl@1.7.0, commander@2.0.0, mkdirp@0.3.5, debug@2.1.0, glob@3.2.3, jade@0.26.3)
+-- grunt-lib-phantomjs@0.4.0 (eventemitter2@0.4.14, semver@1.0.14, temporary@0.0.8, phantomjs@1.9.12)
grunt-contrib-less@0.11.4 ../node_modules/grunt-contrib-less
+-- async@0.2.10
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
+-- maxmin@0.1.0 (pretty-bytes@0.1.2, chalk@0.4.0, gzip-size@0.1.1)
+-- lodash@2.4.1
+-- less@1.7.5 (graceful-fs@3.0.4, mime@1.2.11, clean-css@2.2.18, source-map@0.1.40, mkdirp@0.5.0, request@2.40.0)
grunt-contrib-imagemin@0.8.1 ../node_modules/grunt-contrib-imagemin
+-- pretty-bytes@1.0.1 (get-stdin@1.0.0)
+-- async@0.9.0
+-- chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
+-- imagemin@1.0.5 (get-stdin@3.0.0, stat-mode@0.2.0, ware@0.3.0, nopt@3.0.1, tempfile@1.1.0, fs-extra@0.11.1, imagemin-svgo@1.0.2, imagemin-pngquant@1.0.2, imagemin-jpegtran@1.0.0, imagemin-gifsicle@1.0.0, imagemin-optipng@1.0.0)
_-----_
| | .---------------------------------------.
|--(o)--| | Bye from us! Chat soon. |
`---------´ | |
( _´U`_ ) | The Yeoman Team |
/___A___\ | https://github.com/yeoman/yeoman#team |
| ~ | '---------------------------------------'
__'.___.'__
´ ` |° ´ Y `
Podremos ver que nos ha creado la siguiente estructura, donde podemos observar que nos ha creado los archivos de configuración de Grunt y de Bower, más la carpeta con la aplicación y otra con plugins de Grunt, también son llamados contribs
Ahora llega el momento de la configuración para esto vamos a hacer uso del archivo Gruntfile.js, pero antes de hacer la configuración de PHP en Grunt, voy a contar las partes que interesante tiene este fichero y deberíamos saber identificar.
Función contenedora:
module.exports = function(grunt) {
// el resto de codigo
};
Objeto de configuración del proyecto:
grunt.initConfig({
// dentro ira la configuración de tareas
less: {
dist: {
files: {
'<%= yeoman.app %>/styles/main.css': ['<%= yeoman.app %>/styles/main.less']
},
options: {
sourceMap: true,
sourceMapFilename: '<%= yeoman.app %>/styles/main.css.map',
sourceMapBasepath: '<%= yeoman.app %>/',
sourceMapRootpath: '/'
}
}
},
Mastareas...
};
El registro de Tareas, lleva 2 parámetros el primero es el nombre que después será el que utilizaremos para ejecutar dicha tarea, el segundo es un array y incluiremos las tareas que serán ejecutadas.
grunt.registerTask('test', [
'coffee',
'less',
]);
Ahora si ejecutásemos el código de abajo, la tarea “test” llamaría al objeto de la configuración para realizar los procesos configurados en el, que son los de coffee y less. También tener en cuenta que se pueden crear tareas que llamen a otras tareas, como ejemplo podríamos crear un objeto que se llamase “multiple-test” y este a su vez llamase a “test” y a otras tareas que le indicásemos.
grunt test
Hasta ahora ya hemos dados los primeros pasos y hemos hecho uso de Yeoman, Grunt y Bower si te has dado cuenta cada uno ha cumplido su función según lo que contaba al principio y ya que tenemos instalado todo vamos a probar, puede que antes necesites como yo que cambiar en Gruntfile.js. en las opciones de conect, el puerto y el hostname.
grunt server
Con este comando que necesitaras ejecutar con un user con privilegios, nos creara todos las tareas y nos arrancara el servidor web en mi caso ya que cambie el hostname y el puerto podré ver el resultado en 192.168.1.52:9008 será como esta:
Si nuestro proyecto front-end no necesita paginas dinámicas PHP con esto nos bastaria para comenzar un desarrollo, utilizando HTML5, Bootstrap y Font Awesome, pero podemos ir incluyendo contribs según vayamos necesitando, podéis encontrar plugins de Grunt en el link que dejo, son muy sencillas de instalar, también dejo un enlace que explica cómo se hace por si surge alguna duda, aunque para Grunt-PHP vamos a hacer la instalación de una contrib.
http://gruntjs.com/plugins
http://blog.grayghostvisuals.com/grunt/image-optimization/
Como usar PHP junto a Grunt
Para poder integrar PHP en el servidor de Grunt vamos a tener que conectar con un marco middleware, primeramente el instalaremos plugin connect-php
npm install connect-php
Una vez instalado, vamos a requerir utilizar connect-php y se lo asignaremos a una variable, podemos insertar esto al principio del Gruntfile.js
var miphp = require('connect-php');
Sin más rodeos, ahora vamos a incluir nuestro middleware, para hacerlo esto deberemos hacerlo dentro de Grant.initConfig a su vez en el connect creando la función dentro de la propiedad middleware:
grunt.initConfig({
...
connect: {
options: {
......
middleware: function(connect, options) {
var mymiddleware = [];
var dir = options.directory ||
options.base[options.base.length - 1];
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
mymiddleware.push(miphp(dir));
options.base.forEach(function(base) {
mymiddleware.push(connect.static(base));
});
mymiddleware.push(connect.directory(dir));
return mymiddleware;
}
},
...
}
});
Si hemos realizado todo bien ahora puedes cambiar el archivo de dentro app/index.html por index.php y volver a ejecutar grunt server y entrar en la url 192.168.1.52:9008/index.php entonces podéis ver que funciona perfectamente