Previously, I talked about how Plop can help increase productivity when coding by reducing context switching. In this article, we’ll dive into an example and configure a Plop generator to create a React component in Typescript. By the end, you’ll be able to start using Plop to build your own generators for any type of project and reap the productivity benefits!
Before we start
Please ensure you have Node.js and the npm CLI installed (optionally yarn) and that npm (and yarn) is available on the PATH environment variable.
I will use yarn in my examples but these can all be substituted for the equivalent npm command.
With that out of the way, let’s begin.
1. Create the project
Create a new create-react-app project using typescript:
yarn create react-app plop_example_project --template=typescript
2. Install Plop
We will install Plop as a development dependency within the project. It is possible to install globally making command line access marginally easier, but I prefer to keep projects self-contained wherever possible to reduce the potential for conflict with other projects.
So, installing within the project, type the following in the console:
yarn add plop --dev
This will add the development dependency to your project.
3. Add a ‘plop’ script
Since we have created a local copy, we need to call Plop via the npm scripts. Add the “plop” script to the package.json file:
{
...,
"scripts": {
...,
"plop": "plop"
},
...
}
4. Create the template files
The templates are simply handlebars files (*.hbs) which, at their most basic level, take a set of variables and transform them into a text output. As the name suggests, the placeholders for each variable appear in the template between {{handlebars}} which then get replaced with supplied values when the script is called. The filenames can also include placeholders, something that we’ll take advantage of in this example.
We will create three template files:
Note that the file names take a name variable between handlebars followed by a file extension. When the generator runs, the .hbs extension will be removed and the name populated, leaving us with a filename that fully represents our intended file type.
Create a new directory plop_templates/component and create the three templates, inserting the following code:
{{name}}.tsx.hbs
import React, { ReactElement, HTMLProps } from 'react';
import classes from './{{name}}.module.scss';
export interface {{name}}Props extends HTMLProps<{{type}}> {
}
export default (props: {{name}}Props): ReactElement<{{type}}> => {
return (
<{{tag}} className={classes.Root}></{{tag}}>
);
}
{{name}}.module.css.hbs
.Root {
}
{{name}}.test.tsx.hbs
import React from 'react';
import { render } from '@testing-library/react';
import {{name}} from './{{name}}';
test('renders', () => {
render(<{{name}} />);
});
These three files represent the simplest form any component will take. They use three variables:
The values for these variables are defined when the plop script is called, described in step 6.
5. Create the config file
Now we’ll tie the templates and Plop CLI together to form our generator. We do this by creating a plopfile.js file in the root of our project and populating like so:
module.exports = function (plop) {
plop.setGenerator('component', {
description: 'React component using Typescript',
prompts: [
{
type: 'input',
name: 'name',
message: 'Name: '
},
{
type: 'input',
name: 'type',
message: 'DOM API Type: '
},
{
type: 'input',
name: 'tag',
message: 'Tag name: '
},
],
actions: [
{
type: 'addMany',
destination: 'src/components/{{name}}',
templateFiles: 'plop_templates/component/*.hbs'
},
]
});
};
plopfile.js exports a function that takes plop as an argument from which a generator can be created. In this example, we’ll get values for the three variables name, type, and tag, then use these variables in our handlebars templates.
The first argument passed to the plop.setGenerator() function specifies the name of the generator to run. The second specifies the prompts (where we set the values for the variables) and the actions to take.
Anatomy of prompts
prompts takes an array of Inquirer.js questions. The questions are documented in full here, however in this example we use:
Anatomy of actions
actions takes an array of actionConfigs. In this example, we use addMany which takes the values of the variables, transforms the templates and outputs the new files to the defined destination.
6. Run the command
The generator is now ready to be called. Make sure the console is at the project root and run the following command:
yarn plop component MyComponentTest HTMLDivElement div
Within a couple of seconds, you should see three new files at src/components/MyComponentTest. The CLI output will confirm this.
Inspect the file content to see that the placeholders have all been transformed to the values you have supplied in the command.
The general structure of the command is:
yarn plop [generator_name] [first_prompt_value] [...prompt_values]
You’ll notice that after “yarn plop”, all the other arguments are optional. If more than one generator is defined, the Plop CLI will ask you to choose a generator.
Supplying the prompt values is also optional. If they are included, they must be in the order specified in plopfile.js. If they are not provided, then the message for each prompt is displayed (again, specified in plopfile.js) where you can provide your answer.
The optional arguments make it very easy for new team members, or yourself coming back to a project after while, to use the generators without having to remember a long list of prompts in the beginning.
By now, you should have a decent understanding of how Plop can be used to generate files, individually or in groups. Not only will it help reduce the amount of boilerplate that you write, but if you are anything like me then the productivity and time saving benefits will become so apparent that you’ll wonder what you ever did without it!
Previously published at - https://medium.com/@fgmonaghan/boost-your-coding-productivity-with-plop-tutorial-68f2a50b15f3