Generate React Component Folders Using Yeoman and NPM

Tony Pettigrew

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:

  1. The path to the template
  2. The name and path where the generated file will be output
  3. 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!