yeoman

Roll Your Own Yeoman Generators

Prior to my last attempt to use Yeoman, I had tried on three separate occasions to start a project with it. All three times ended in overwhelming confusion, and a feeling that I was so far behind on the state of web development that maybe I should just quit and start making and selling my own bumper stickers at the Saturday market. I’m really glad I was born with the gift of stubborn perseverance, and a sharp sense of revenge. I became determined to make Yeoman my bitch, and as it turns out, it wasn’t that hard…it wanted to be my bitch all along.

rooster skull line

All of the Things!!!

I think as a web developer I have a propensity to try to take on too many “best practices” all at once. This is because I spend a lot of time with my head down on a project, and when I get the chance to look up, everyone is gone. On to the next one. When I start something new therefore, I spend time catching up on the state of the world. I found Grunt, Bower, and Yeoman. They got me with the sales pitch, generating templates, automating tasks, managing client side dependencies. It all sounded amazing — and it really is.

I installed Yeoman and ran $ yo webapp, it created a massive code pile of everything incredible, that I had never heard of. The Gruntfile it produces is like a 373 line episode of LOST written in javascript. LiveReload, compass, jshint, uglify, regarde, concurrent, htmlmin, and the list could go on for days. Enraged by my own ineptitude I began frantically reading source code trying to unravel the mystery. I crashed, I collapsed, discouraged and broken. I couldn’t do it.

I think the sad truth is that a huge percentage of web developers are not using most of the tools Yeoman gives you. The teams at Yeoman, Grunt, and Bower are doing innovative and amazing things, I truly believe they’re changing the course of javascript web development forever. Their excitement to showcase the power of their platform is understandable, but they may have lost touch with the plight of the common dev. Having $ yo webapp as the first action in “getting started” is like a fireman trying to get a kitten out of a tree — with a fire hose.

Just Grunt.

Just do one thing with grunt. For me, it was running automated unit tests. Oh Jesus please! That would be enough! I decided to let the big picture of yo and bower slide a little, and to start with the Grunt documentation. My first Gruntfile copied something from one directory to another, but that simple task helped me understand what Grunt was, and shaped a crude understanding of how I could make things happen. That story is documented here Testing Javascript with RequireJS Modules and Mocah and The Best Way to Test RequireJS Code with Mocha, PhantomJS, and Grunt. Forgive the name of the second one, there’s no such thing as “the best way” to do anything. It should say “the best I’ve been able to do.”

As I used grunt more and more, it became obvious I couldn’t live without it. So I came back around to Yeoman, and tried again.

I failed again.

There were still way too many things I didn’t understand. I spent another month or so occasionally playing with my Gruntfile’s trying do more. I learned how to automate compilation of my .less files, used JSHint, tested with karma (testacular), managed a build process, and finally I conquered my nemesis — Livereload. I didn’t really do anything, they put livereload into grunt-contrib-watch as an out of the box option. None the less, it was a major victory for me. I think understanding how to use grunt-contrib-watch was the key to harnessing the power of Grunt. If you’re just getting started, start with the basic grunt docs, and the readme for that plugin.

Finally I am at a point where I can do $ yo webapp, look at the resulting file structure, and make sense of it. In fact, I understand it well enough to know that I don’t really even like it. I like my setup.

THERE IT IS!!! That is the epiphany.

Yeoman isn’t about taking plays from someone else’s playbook, its about designing your own offensive scheme, and executing it.

Yeoman Generators

Enter the age of yeoman generators. The first thing you need to do is read Write Your First Generator. I mean it, you need to read it from top to bottom, run the commands, edit the files on your computer, the whole nine yards. That sounds like a drag right? A real waste of time. Nope, fortunately it is probably the single most entertaining, informative, and useful walkthrough ever written. It is required reading. Follow @stephenplusplus so you can keep up with anything else amazing he’s able to produce.

Once you’ve done that, start applying what you have learned.

$ yo generator

That generates a generator. Your mind just imploded.

My approach was to take a project that I had configured just the way I like, and start copying files out of it and into the app/templates/ directory of my new generator.

I haven’t gotten beyond dirt simple prompts such as, “What do you want to call your module?” And “What is your name?” But its still really useful.

generator-foo/app/index.js

// Code up here
...

var prompts = [{
  name: 'moduleName',
  message: 'What do you want to name this module?'
},
{
  name: 'authorName',
  message: 'What is your name?' 
}];

this.prompt(prompts, function (err, props) {
  if (err) {
    return this.emit('error', err);
  }

  this.moduleName = props.moduleName;
  this.authorName = props.authorName;

  cb();
}.bind(this));

// More code down here
...

Let’s say you type in “Gangnam Module” for module name, and “Psy” as your name. Then you setup templates like:

_package.json

{
  "name": "<%= _.slugify(moduleName) %>",
  "version": "0.1.0",
  "private": true,
  "author": "<%= authorName %>",
}

And what will be produced in the generated “Gangnam Module” output is:

package.json

{
  "name": "gangnam-module",
  "version": "0.1.0",
  "private": true,
  "author": "Psy",
}

With just that basic understanding, in a few hours I was able to completely change the way I write backbone.js modules. I had developed a practical setup for developing, but it would take hours of setup to put a project together, configure all the grunt tasks, copy this from here, that to there, and so on and so on. Now I just run my generator-backbone-module and it produces a skeleton that allows me to repeatedly, quickly and consistently produce projects like backbone-gcl.

A few simple commands.

$ npm install generator-backbone-module -g
$ cd mkdir backbone-thing && cd $_
$ yo backbone-module
What do you want to name this module? (backbone-thing)
What is your name? (Will Vaughn)
... yeoman runs
...
...
$ grunt
> starts a nodemon server...
$ grunt watch
> starts my file watchers for all my testing and jshint needs.

Then I write tests, then I write code. Then I $ bower register and I’m done.

Get to it friends! It’s a lot of fun, I haven’t felt this powerful in a long time. If you found this useful, the best thing you can do for me is put it on hacker news or reddit, you can check my profile out on github nackjicholson, or on twitter @nackjicholsonn. If you have questions, suggestions, fixes, or ignorant shit on your mind, there is a convenient comment box below.