Digit Geek
yeoman
Digit Geek > Recent Articles > Technology > How to accelerate your web development with Yeoman

How to accelerate your web development with Yeoman

Get started with Yeoman, a tool that helps you kick-start new projects easily and helps you stay productive by plugging you into a vibrant generator ecosystem

Yeoman is a scaffolding tool that helps you kick-start new projects and prescribes the best practices and tools to help you stay productive. In order to achieve that goal, Yeoman basically provides you with a generator ecosystem that helps to scaffold either a complete project or at least some part of it.

What is scaffolding and why do I need it?

This concept basically came from Ruby, another very popular programming language where you can say something like rails generate scaffold model_name and it would basically generate the required code that your application would need to interact with the system. This is something like maven archetypes if you are coming from a Java background.

When to use Yeoman?

It’s good to use Yeoman when you want to create an application that requires some basic configuration. Suppose there are similar types of projects being developed at your office and you know that there are some basic codes required to start off with the application, then you can create a generator for that. There are a lot of community-made generators available that can help you to scaffold the project. You can find all of the official generators on their website or by going to: http://yeoman.io/generators/

Here, we are primarily focusing on how to create a generator. So the basic requirement of this article is some preliminary knowledge about nodejs and JavaScript, specifically ES6. All of the code that is written over here is following ES6 Syntax whenever possible. You need to have nodejs and npm installed on your system to follow along with this tutorial.

Setting up the generator

First check whether you have nodejs installed in your system by typing
$ node -vIf

If you don’t have nodejs installed, do so from  https://nodejs.org/en/

Next, you have to install Yeoman. Because it’s an npm package, this is simple:
$ npm i -g yeoman

Now, the Yeoman team has created a generator in order to create generators! To install this, you will need to use npm:
$ npm i -g generator-generator

Note: If you face any kind of access rule limits then you must run the above commands with admin access.

After you are done with the steps above, you can now create your own generator. Our goal is to create a basic express application. First, you have to run the generator that you just installed, in the directory where you want to create the generator.
$ yo generator

After running the above command you will be greeted with the basic prompt for Yeoman. Prompting is a very important concept in Yeoman. You will be asked to give some basic information about the generator here.

Yeoman

The generator also creates a folder and performs the necessary npm installation. Additionally, there are some nifty features using inquirer.js where you can provide some checkboxes and various dropdowns and styles in your generator to enhance the user experience.

After everything is done the file structure should look like this:

Yeoman

If we were to describe the folder structure, then the folder that you should be interested in is the generators folder. There is basically only one folder in the generators folder and that is your app folder. This folder contains the necessary files that are required to start off with your generator. The index.js contains the logic to run your generator and the templates folder contains the files that are required for your generator to run. Yeoman also creates some required files such as .editorconfig, .eslintignore, etc.

Now if you view the package.json file, you will find that the Yeoman generator has created some other files – some dependencies and devDependencies.

First coming to the dependencies, you can see a basic package Yeoman-generator has been added. That package is basically the heart of the project. Every generator must have this package as a dependency.

Other two packages are chalk and yosay. chalk is a package that helps to colorize the text in the console. Because Yeoman is a CLI-based application, you’re going to want to enhance the user experience by colorizing it. yosay adds some cool things to your CLI. For example, you can get it to do something like cowsay, but without the stupid cows!

For example: 
const yosay =
require(‘yosay’);
const chalk = require(‘chalk’);console.log(`Hello ${chalk.red.underline(process.env.USER)}. This is a test string.`);

Will generate an output as shown below:

Yeoman

Set Up the template folder

Now, coming to the project your goal is to create a simple application, such as a basic express application. You will need a javascript file that is basically the backend as well as a frontend file that will be communicating with the javascript app.

Yeoman

The file structure is very simple. The first step is to make sure all the required files exist in the project’s directory or are created in the template directory. So we create the required files and folders accordingly. So after creation of the template files and folder the template folder should look like this:

Yeoman

Next, you need to add some code into the app.js and view.html. Remember that these code snippets are going to be copied to the destination path where someone will eventually generate the sample project. Our suggestion is to make it as readable as possible right in the beginning, and to add comments whenever possible, to give the person working with your code an idea of how and why things are working.

Get sample code for app.js here.

If you look at line 38 and 39, we are using the EJS Template syntax to inject values – more on that later.

Here’s a sample of the view.html.

Now that you’re ready with your basic template files, you can move on to the bit where you need to take user inputs depending on your requirements, and scaffold the project accordingly.

Coding the generator

In any generator, the main file resides at index.js within the generators folder.If you look inside the file, you will see a class that is extending the class Generator that came from the yeoman-generator package. If you are new to the concept of extending in JS, you need to read up on that now.

In any generator, the main file resides at index.js within the generators folder.

If you look inside the file, you will see a class that is extending the class Generator that came from the yeoman-generator package. If you are new to the concept of extending in JS, you need to read up on that now.

The yeoman run-loop

There are some methods that are defined within the class. Any generator class can have some any number of methods. Each method that is directly attached to the generator prototype is considered to be a task. Each task is run in sequence by the Yeoman environment run loop. In other words, every method that is in the class will get called.

This can be a problem in case you want to create some helper or private methods that you don’t want called when other tasks are being executed. To create a private method you need to add _ (an underscore) before the method name so that the Generator does not execute that helper method. Another way to create helper methods to add them to the instance variable – create a set of instance methods whenever you want to create some helper methods.

The Yeoman run loop prioritises methods using the Grouped-queue module. Priorities are defined in your code as special prototype method names. When a method name is the same as a priority name, the run loop pushes the method into this special queue. If the method name doesn’t match a priority, it is pushed in the default group. The generator follows an available list of priority methods (in running order):

  1. initializing: Your initialization methods (checking current project state, getting configs, etc)
  2. prompting: Where you prompt users for options  – you’d call this.prompt()
  3. configuring: Saving configurations and configure the project (creatin .editorconfig files and other metadata files)
  4. default: If the method name doesn’t match a priority, it will be pushed to this group.
  5. Writing: Where you write the generator specific files (routes, controllers, etc)
  6. conflicts: Where conflicts are handled (used internally)
  7. install: Where installations are run (npm, bower)
  8. end: Called last, cleanup, say good bye, etc

Now, these methods are called in sequence and if you want to add some method in some group you may group them likewise.

Async

There are many ways to stop the yeoman run-loop and the easiest one is to return a promise. The run-loop will halt till the promise is resolved or will exit whenever the promise is rejected. Now if you are using some old libraries that do not support promise yet then you have to use this.async to halt the run-loop, like mentioned here.

Handling User Response

Your generator will interact a lot with the end user and though Yeoman is primarily based on CLI, its sheer flexibility allows any generator to be run in any environment. Yeoman provides a set of abstractions to the end user, and it’s your responsibility as an author to use the abstractions.Yeoman uses the prompt module provided by inquirer.js. You should refer to their list of APIs for a list of options available to the user. The prompt method is asynchronous and returns a promise. You will need to return the promise from your task,

Yeoman uses the prompt module provided by inquirer.js. You should refer to their list of APIs for a list of options available to the user. The prompt method is asynchronous and returns a promise. You will need to return the promise from your task, and wait for it’s completion before running another.

In our example, you will first see the line for logging where this.log is used, and whenever logging some output you should also use this.log instead of console.log because that is in the current running context of the generator. In our example, we’re asking the user about:

  • Name
  • Email id (with validation)
  • The app’s name
  • The port value in which the user would like to create the application (default port: 3000)
  • The license

Thus, after adding each of the prompts, our prompting function should look like this:

We encourage you to add some prompts to get an idea about how differnt types of prompts work.

Our index.js has a lot of code to digest. Starting with the prompt function, we are adding a prompt whenever data is required. At the end of the prompt, we handle the promise and add the answers to Yeoman’s run context.

Next, at the writing function, we add the required code for copying values from source to destination.

Working with filesystems is very easy in Yeoman, because it provides a lot of utility functions in the code. The Yeoman generator context has all the functions mentioned within the code itself to make life easier.

In the writing function, you first need to prepare our package.json, then you overwrite the value in the package.json file. In Yeoman, there are mainly two contexts are defined for file operation. The first is the destination context, and the second is the template context. The destination context is just the folder where the user is running the application.

Suppose you are running your application in ~/Projects. For that project this.destinationRoot() => returns ‘~/Projects’ and this.destinationPath(‘index.js’) => returns ‘~/Projects/index.js’.

The important thing about any copy function is that when something is missing, Yeoman will create that directory or file for you. You don’t have to explicitly create every file or folder, and all operations are synchronous.

In the template context similarly, this.sourceRoot() => returns ‘./templates’this.templatePath(‘package.json’) => returns ‘./templates/package.json’

Now at line 88 you can see we have used the copyTpl method to overwrite the EJS compliant variable to assign a dynamic port number to our project here.

After copying everything the last step that remains is installing the required modules for your code to run. We are only using express, so we will install express in the end. If you need to, you can use other modules. Also, there is another feature where you can add ‘save-dev’:true and install some devDependencies.

In the end, to wrap up, we are sending another yosay message to the user to inform the user what else needs to be done to start the app.

If you have gotten this far, there’s just one step that remains – linking the package. To do that, at the generator directory write npm link.

Yeoman

After linking create a test directory to test-run your generator.

Yeoman

Yeoman

Now, in the test directory, you will see all the files are created with the relevant values replaced. All you need to do to start the app is send out the command: npm start

Yeoman
The final output of the generator

Yeoman

Yeoman

In the end

There are a lot of scaffolding tools in the market and Yeoman is only one of them. And beyond this article, there are certainly a lot of other parts to be uncovered. There are some pretty awesome generators available over there and you can publish your own awesome one too.

Read More: http://yeoman.io/
Inquirer: https://github.com/SBoudrias/Inquirer.js/
Our Code: https://github.com/TechnicalRhino/generator-yeoman-tuts


This article was first published in the September 2017 issue of Digit magazine. To read Digit’s articles first, subscribe here or download the Digit app for Android and iOS. You could also buy Digit’s previous issues here.

Agnibha Bose