Generate React Component Folders Using Yeoman and NPM
Tony Pettigrew / September 07, 2022
6 min read • ––– views
Table of Contents:
Do you ever wonder how much time you spend manually creating folders and files for React components? If you're like me and it has become a tedious endeavor, keep reading because I will show you how to automate this process and publish your own Yeoman generator for future projects!
Technologies you will learn about:
- Yeoman
- Publishing NPM Packages
You can find the example repo here.
Getting Started
First, you will need to create a directory and open it with a code editor of your choice. The directory must begin with the word generator: generator-your-generator-name
. You can either npm init
or create a package.json file manually but it must contain yeoman-generator
in its keyword list. It should look something like this:
{
"name": "generator-name",
"version": "0.1.0",
"description": "",
"files": [
"generators"
],
"keywords": ["yeoman-generator"],
"dependencies": {
"yeoman-generator": "^1.0.0"
}
}
Next, run:
npm install yeoman-generator
Folder Structure
For the sake of this tutorial, we will be creating a single, default generator but Yeoman allows us to create multiple sub-generators based on the project's folder structure. In that case, each sub-generator would be kept in its own folder, within the generators directory.
The default generator used when we run npx yo generator-name
is the app generator. It will be kept in the generators/app
folder:
├───package.json
└───generators/
├───app/
└───index.js
Writing The Generator
So far, you should have a project root directory with a package.json. We are going to create the generator file which contains our business logic. From the project root run:
mkdir generators
touch generators/index.js
In index.js, write:
const Generator = require("yeoman-generator");
module.exports = class extends Generator {
constructor(args, opts) {
super(args, opts);
this.log("Creating component...");
}
myFirstMethod() {
console.log("Running my first method");
}
done() {
console.log("Finished!");
}
};
Let's perform a quick sanity check to ensure that the generator is working. To be able to use the generator locally without publishing to NPM, run:
npm link
Now run, where generator-name
is the name of the generator without generator-
in front of it:
npx yo generator-name
And you should see 3 logged outputs. The console.log in the constructor should run first, then the method and you guessed it, onDone should run last.
Now that we've confirmed that everything is setup correctly and we can run our generator locally to test the changes that we make in development, let's work on allowing the user to pass in a folder name via the CLI.
User Input
You can pass an argument to the generator by entering a word after the base CLI command like so: npx yo generator-name argument
. To receive the argument in the generator file, add this to the constructor:
constructor(args, opts) {
super(args, opts);
this.log("Creating component...");
// Add the following:
this.argument("name", {
type: String,
required: true,
description:
"The name of the component. This will also be the name of the directory containing the component.",
});
}
We told our generator to store the argument as name
, that the input will be a string, that the argument is required, and a description. The argument can now be accessed in the generator via this.options.name
.
To test our changes, change your method to:
myFirstMethod() {
console.log("my arg is", this.options.name);
}
And run the generator with an argument, you should see it in the console when the generator completes.
We now have user input, great!
Generate The Component File
Another important aspect of writing your generator is templating. Similar to handlebars or pug you can plug variable values into your generated files. Delete your myFirstMethod
method and replace it with a method called writing
.
First, we will write the code to generate our react component from a template, then we will create the template file, so bear with me.
Add this to the writing
method:
writing() {
this.fs.copyTpl(this.templatePath("component.jsx"),
this.destinationPath(this.options.name + ".jsx"),
{
name: this.options.name,
});
}
Let's break this down before moving on. this.fs.copyTpl
generates a copy of your template file and passes your variables to the template. It takes three arguments:
- The path to the template
- The name and path where the generated file will be output
- An object with variables that will be passed to the template
this.templatePath
just needs the name of your template file.
this.destinationPath
takes the path, from the project root, where you want your file to be generated.
Write The Template
Now, we need to create the template file that this.templatePath("component.jsx")
is referencing. To do that run:
mkdir generators/templates
touch generators/templates/component.jsx
In component.jsx, you will have access to your name
variable that you passed in from this.fs.copyTpl
with this syntax: <%= name %>
.
Write this in your component.jsx template file:
import React from 'react';
export default function <%= name %>() {
return <div><%= name %></div>;
}
Now run your Yeoman generator CLI command with an argument and it should generate a React component using the template. For example:
npx yo generator-name CoolComponent
You should see a new file called CoolComponent.jsx in the root directory. Congrats! You've now automated a task that will save you time during the development process. If you'd like to see a more complex example, here is the generator that I created to automate the creation of feature folders and tsx components.
Next, we'll publish our genertor.
Publish To NPM
The next thing we'll want to do is create a repository on github and commit/push all of our work so far. Make sure to delete the CoolComponen.jsx that was generated in the last section and create a .gitignore file which tells git to ignore the node_modules folder.
Once you have pushed your project to github. Log in to NPM from the project root using the CLI if you need to. If you have not done this before, you will need to create an NPM account and then, in the project root, run:
npm adduser
Once logged in, you should be able to run:
npm whoami
And your username will be logged to the conole.
Now you can run:
npm publish
And in a few moments your package will show up in your NPM account under packages. Now you can install your generator into any future project using npm:
npm install -D generator-name
and use it in your project like so:
npx yo generator-name MyComponent
There is a lot more you can do with Yeoman generators, such as add CLI flags or formatted console messages. Check out the docs for more inspiration!