Writing Custom Yeoman Generator
Writing a custom Yeoman generator, you need to install generator-generator first.
(generator-generator) Scaffolds out a new basic Yeoman generator with some sensible defaults.
So it creates some basic structure for writing your own custom generators. It is a generator for writing Node generator application.
First Install generator-generator:
$ sudo npm install -g generator-generator
Then generate some basic files for writing your own generator by issuing:
$ yo generator
You can use generator-generator to write both a custom generator and a custom sub-generator. What is sub-generator? For example, Angular directive or service is a sub-generator.
Use naming convention generator-[name]
.
Create a directory for your new generator:
$ mkdir -p ~/generators/generator-hello && cd $_
Make sure entering the newly created directory (cd $_
), otherwise all files generated will be placed under the current directory. Then, scaffold your generator:
$ yo generator
As versions [email protected] and [email protected], the generator creates the following directories and files:
|
|
You might want to make your initial commit:
$ git init && git add '*' && git commit -m 'Initial commit'
While in development, make it accessible globally:
$ sudo npm link
This is similar to:
$ sudo npm install -g [generator-name]
They both will be discoverable from /usr/local/lib/node_modules
.
There isn’t much going on there, we need to customize our own generator. The main file is ./app/index.js
.
|
|
The HelloGenerator
extends Base generator. There are four properties (functions) that it has extended: init
, askFor
, app
, and projectfiles
.
All these functions will be invoked by Yeoman one by one in order (the order is important), meaning that init
will be called first to perform initialization, and then askFor
will be called to get user prompts, then app
and projectfiles
will be called afterward to build the application.
However, it is not a must to have four properties, it just brings more structure and modularity. In fact, you can merge all four functions into a single one.
The method name does not matter. Just don’t name it prompt
because you will override the existing property inherited from yeoman.generators.Base
.
If we need to declare a “private” property, just appending it with an underscore as a hidden property, e.g. _dontAskFor: function(){}
, or if you just use it in the same file, you can simply define a global function myFunc()
.
Personal, I don’t think it is necessary to break it into many functions, three are enough, initialization, prompting user for input, and generating files.
When choosing property names, the Base object contains many properties which is not a good idea to be overridden, such as ["append", "help", "log", "prompt", "remote"]
. This design has limitation on choosing a right property name. For example, I was thinking about using prompt
instead of askFor
, but prompt
is an inherited property. Therefore, it is a good idea to keep fewer properties in HelloGenerator
. Three are enough. All these properties can be accessible from the context this
. From this
object you can access everything from Base object to newly defined _dontAskFor
hidden property.
Time to test the custom generator:
$ cd /tmp && mkdir hello && yo $_