¿Cuántas veces en nuestros proyectos repetimos la creación de archivos?¿Cuánto tiempo podemos gastar en realizar esta tarea tan repetitiva? Seguramente la respuesta a estas dos preguntas es la misma para todos los que desarrollamos, ya que es una tarea repetitiva en los proyectos. Para solucionar este pequeño problema tenemos Plop.

Plop es un “micro-generator framework” que ejecutaremos en nuestra terminal. A través de preguntas que responderemos, realizará acciones que programemos para generar una template con el código que queremos. Estas acciones a realizar pueden ser crear un nuevo archivo, modificarlo o crear múltiples archivos de una única vez por ejemplo.

Por lo tanto, es una herramienta que nos evitará repetir esta tarea de forma manual, automatizando y ahorrándonos tiempo para que nuestro único foco sea el desarrollo.

Esta herramienta se apoya en “Handlebar” para la creación de las templates y la librería “inquirer.js” para los prompts que se mostrarán en la terminal.

Instalando Plop

Para poder utilizar Plop, necesitamos tener node y npm. Podemos instalarlo como dependencia de desarrollo en nuestros proyectos:

npm i --save-dev plop

O bien también podremos instalarlo de manera global si lo deseamos:

npm i -g plop

A continuación tendremos que crear un archivo en la raíz de nuestro proyecto con el nombre “plopfile.js” con el siguiente aspecto:

module.exports = function (plop) {
        // create your generators here
        plop.setGenerator('basics', {
               description: 'this is a skeleton plopfile',
               prompts: [], // array of inquirer prompts
               actions: []  // array of actions
        });
};

Y por último añadiremos el script en el “package.json” de nuestro proyecto con el que ejecutaremos el código:

{// Package.json
"scripts": {
    "plop": "plop"
  }
}

Ejemplo básico

Una vez que ya tenemos instalado Plop, vamos a empezar con un ejemplo básico donde generaremos desde una template un nuevo archivo simulando el aspecto que pueden tener nuestras views en un proyecto React.

Para ello tendremos que añadir en nuestro “plopfile.js” lo siguiente:

// Basic Example
module.exports = function (plop) {
  plop.setGenerator('Basic Example', {
    description: 'Create a view',
    prompts: [{
      type: 'input',
      name: 'name',
      message: 'Screen name',
    }],
    actions: [{
      type: 'add',
      path: `src/screens/{{name}}/{{name}}.js`,
      templateFile: 'plop-templates/screen/screen.js.hbs',
      abortOnFail: true,
      skipIfExists: true,
    }],
  });
}

Expliquemos por partes en que consiste el código anterior.

Plop utiliza Generators, una lista de las opciones que veremos en nuestra terminal cuando ejecutemos este archivo. Para poder crear este generator, utilizamos “setGenerator” que recibe dos argumentos:

El array de objetos que hay en “prompts” sigue el formato de la librería “inquirer.js”. En su documentación podemos ver todos los tipos de prompts que podemos añadir.

En nuestro ejemplo, nos mostrará un input que nos preguntará por el nombre que queremos poner a nuestra screen y quedará guardado en una variable que se llama “name”, tal y como la hemos nombrado en la propiedad “name” del objeto.

Una vez respondido a las preguntas que se nos muestra, se ejecutará la acción que hemos añadido que consiste en añadir como hemos indicado en su type un nuevo archivo en el path que nosotros hayamos decidido.

Para crear este archivo va a utilizar la template que tenemos dentro de nuestra ruta /plop-templates. Su aspecto es el siguiente:

import React, {useState, useEffect} from 'react';
const {{name}} = () => {
  const [state, setState] = useState();
  useEffect(() => {
  }, []);
  return (
    <div>
      {{name}} SCREEN
    </div>
  );
};
export default {{name}};

Es el momento de ejecutar el script para crear nuestro primer archivo desde el ejemplo anterior. Para ello, lo único que tenemos que hacer es desde la raíz de nuestro proyecto lanzar el comando:

npm run plop

Y ocurrirá lo que se ve en el siguiente gif:

El resultado final de la acción es la creación, dentro de /src/screens/, de una nueva carpeta con la screen creada como se puede ver en la siguiente foto:

Ejemplo con varios generadores y distintas acciones

Después de haber visto un ejemplo sencillo para entender lo más básico de Plop, vamos a realizar un ejemplo un poco más elaborado donde tendremos distintos generadores y además según la opciones que elijamos crearemos en una única acciones varios archivos utilizando “addMany” como tipo de acción.

Para este ejemplo, hemos sacado en 3 archivos individuales la configuración de los GeneratorConfig. Estos 3 archivos serán:

  1. Component.js: Nos da la opción de crear un component.
  2. Redux.js: Nos permite crear un flujo de redux creando una acción o un flujo de redux para un petición http.
  3. Views.js: Nos permite crear una screen como la del ejemplo básico.

Ahora nuestro plopfile.js tendrá el siguiente aspecto:

const { component, redux, views } = require('./plops');

module.exports = function (plop) {
  plop.setGenerator('Component', component);
  plop.setGenerator('Redux', redux);
  plop.setGenerator('Views', views);
}

Si ahora ejecutamos el script, se nos preguntará qué generador queremos usar de los 3. En nuestro caso elegiremos Redux para explicar el funcionamiento con una lista de opciones en nuestro prompts. El archivo de configuración de redux tiene el siguiente aspecto:

module.exports = {
  description: 'Create a redux action or redux flow',
  prompts: [
    {
      type: 'list',
      name: 'action',
      message: 'What would you like to create',
      choices: ['An Action', 'Redux flow'],
    },
    {
      type: 'input',
      name: 'name',
      message: 'Action Name',
    },
    {
      type: 'input',
      name: 'path',
      message: 'path',
    },
  ],
  actions: (data) => {
    let actions = [];
    if (data.action === 'An Action') {
      actions = actions.concat([{
        type: 'add',
        path: `src/components/{{path}}/{{name}}.js`,
        templateFile: 'plop-templates/component/{{name}}.js.hbs',
        abortOnFail: true,
      }]);
    } else {
      actions = actions.concat(
        {
          type: 'addMany',
          destination: 'src/actions/{{path}}/',
          base: 'plop-templates/reduxFlow/',
          templateFiles: 'plop-templates/reduxFlow/*.hbs',
          abortOnFail: true,
        },
        {
          type: 'add',
          path: `src/reducers/calls/{{path}}/{{name}}Requested.js`,
          templateFile: 'plop-templates/calls/calls.js.hbs',
          abortOnFail: true,
        },
        {
          type: 'add',
          path: `src/sagas/{{path}}/{{name}}.js`,
          templateFile: 'plop-templates/sagas/saga.js.hbs',
          abortOnFail: true,
        }
      );
    }
    return actions;
  }
};

Si nos fijamos en la propiedad Actions, ahora estamos pasando una función que va a retornar el array de acciones.

En el parámetro data que recibe la función, tenemos acceso a las respuestas que hemos dado a las preguntas de nuestro prompt. En nuestro ejemplo, accedemos a esta propiedad para conocer la respuesta dada a la pregunta ‘¿Qué quieres crear?’, y así poder realizar la acción correspondiente.

Para nuestro ejemplo, vamos a imaginar que nuestro flujo de redux de llamadas http va a suponer crear siempre los siguientes archivos:

Para ello vamos a encadenar 3 acciones distintas utilizando “addMany” y “add”.

Para crear las 3 primeras acciones de redux, utilizaremos la opción “addMany” de Plop. Con esta opción podemos crear varios archivos a la vez en una única acción. Las propiedades que vamos a usar para este tipo de acción son las siguientes:

A continuación, podemos ver todo el flujo de creación que realizamos con Plop y el posterior resultado:

Conclusión

Como hemos visto, Plop es una herramienta que nos va a permitir crear los nuevos archivos con consistencia en un equipo de desarrollo.

Desde mi punto de vista, la incorporación en nuestros desarrollos puede conseguir que nos ahorremos mucho tiempo en la realización de un trabajo repetitivo como es la creación de los nuevos archivos. Puede merecer la pena que perdamos un poco de tiempo en configurar los distintos “generators” que necesitemos, pero a futura será tiempo que nos ahorraremos.

Los ejemplos que hemos hecho en este post lo puedes encontrar en el siguiente repo .En él solo se hemos visto algunas posibilidades de la herramienta, pero el abanico de opciones es mayor como se puede ver en su documentación, donde nos muestra más opciones: modificar archivos, crear nuestras propias acciones, crear helpers para transformar cadenas de texto, etc.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.