Los procedimientos computarizados no sufren estos problemas, sin embargo dependen de lo que el humano les indique que deben hacer, es un ciclo iterativo, el tema está en que si el humano solo se dedica a una tarea a la vez tiene más probabilidades de no cometer errores, pero una máquina puede hacer varias tareas a la vez de forma exacta.
A lo que queremos llegar es que en un ambiente de desarrollo podemos hacer el algoritmo para varias tareas, una a la vez de forma manual, pero si programamos alguna herramienta que las lleve todas a cabo entonces nos garantizamos que se ejecuten como si fuese la primera vez y sin problema alguno.
Requisitos
Este es un tutorial avanzado, por lo que vamos a requerir varios aspectos que se deben tener y dominar:
Tareas múltiples
Las tareas múltiples en Grunt son muy parecidas a las tareas simples, en el sentido que nos permite lograr automatizar algún proceso, pero a diferencia de las tareas simples las tareas múltiples aceptan configuraciones diferentes, por lo que una misma tarea ejecutada con diferentes parámetros puede tomar un camino u otro que hayamos definido.
Aquí es importante no quedarnos con la ilusión que Grunt sabrá que hacer, ya que es responsabilidad propia de cada desarrollador de definir todo lo que Grunt debe hacer, esto lo logramos con opciones de configuración y así cada tarea que tenga múltiples opciones puede tener un camino a seguir de lo que le podamos indicar.
En el siguiente ejemplo vamos a realizar la copia de unos archivos en particular, sin embargo la parte interesante es que vamos a definir dos sets de copias y según el camino que deseemos nuestra tarea hará una cosa u otra, convirtiéndola así en una tarea múltiple.
Definiendo la tarea
Empezaremos por definir la tarea múltiple, para ello en vez de utilizar registerTask debemos utilizar registerMultiTask, esto nos va a dar un constructor del objeto de tareas diferente que nos permitirá lograr los objetivos que estamos persiguiendo.
Luego vamos a iterar sobre un objeto llamado this.files esto lo que hace realmente es obtener los elementos que pertenecen a archivos, lo cual veremos un poco más adelante, en el bloque forEach que le acompaña es donde haremos el copiado correspondiente y al final de la tarea imprimiremos todo en el log que nos permite mostrar por pantalla Grunt.
Veamos a continuación el código inicial de nuestro ejemplo:
grunt.registerMultiTask('copiar', function() { this.files.forEach(function(file) { grunt.file.copy(file.src, file.dest); }); grunt.log.writeln('Se han copiado: ' + this.files.length + ' archivos'); });Una vez que tenemos la tarea definida de forma adecuada debemos pasar a la siguiente fase, que no es más que definir la configuración de nuestra tarea múltiple que habíamos indicado al inicio del ejemplo, esta configuración se estructura de una forma lógica en la cual le decimos que tiene varios objetivos.
Vamos entonces a construir nuestra configuración donde utilizaremos el siguiente código:
grunt.initConfig({ copiar: { target1: { files: { 'destino/archivo1.txt': 'origen/file1.txt', 'destino/archivo2.txt': 'origen/file2.txt' } }, target2: { files: { 'destino/archivo3.txt': 'origen/archivo3.txt', 'destino/archivo4.txt': 'origen/archivo4.txt' } } } });Ya que tenemos nuestra tarea definida y su configuración, es hora de hacer que nuestra tarea se ejecute, para ello debemos llamar a nuestra tarea desde la consola e indicar el target que deseamos, ya con ello Grunt sabe que debe hacer lo que le hemos programado, veamos como luce esto en la consola en la siguiente imagen:
Si ahora revisamos nuestra carpeta de destino veremos cómo los archivos se encuentran ahí:
Si ejecutamos nuestro target dos y volvemos a revisar la carpeta veremos que hemos copiado todos los archivos:
Esto puede parecer un poco complicado a primera vista, sin embargo una vez que tomemos conciencia de cómo realizar estas tareas se hará mucho más sencillas de ejecutar, algo que podemos tomar en cuenta es que si no conocemos los targets o queremos que todo se ejecute de forma completa simplemente al llamar directamente a la tarea esta va a ejecutar todos los targets que tenga en su configuración como podemos ver en la siguiente captura de pantalla:
El objeto multitask
Ya que vimos una aproximación inicial al mundo de las tareas múltiples en Grunt, es pertinente hablar un poco del objeto multitask que es quien nos permite realizar muchas de estas acciones, al conocerlo podremos entonces decidir cómo utilizar lo que nos ofrece de forma consciente y no por malos usos o vicios desarrollados al escribir tareas sin un conocimiento de lo que estamos haciendo.
Empezaremos viendo las propiedades más importantes de este objeto y describiéndolas de forma breve para que podamos empezar a generar el conocimiento.
Como vemos el objeto multitask tiene algunos componentes interesantes que al conocerlos nos abre el horizonte de lo que nos puede ofrecer Grunt en este tipo de configuraciones múltiples.
El conocimiento de las propiedades del objeto multitask es muy importante, aquí solo mostramos lo más importante, sin embargo en la documentación oficial podemos encontrar mucha más información, a pesar que está en Inglés con un poco de trabajo con los traductores libres como el de Google en caso que no dominemos el idioma seguro que podremos hacernos a la idea de cómo funciona a profundidad este objeto.
Con esto hemos finalizado el tutorial, aprendimos como hacer una tarea con varias secciones que se ejecutan por separado o todas juntas dependiendo de cómo hagamos el llamado de la misma, este llamado puede ser manual o también desde una tarea, por lo que vemos que el entorno de automatización crece un poco en complejidad pero a medida que un proyecto se hace más grande esto es necesario para lograr los objetivos que nos planteamos.