I'm taking a quick break from the shiny land of CSS animations. Back to the black and white (or green and white, or whatever your console colors are) land of workflow automation, with a quick explanation of what it took to build my first generator for Yeoman: generator-playground.
A bit of context
I got tired of always repeating the same steps when I wanted to make a quick HTML/CSS/JS experiment or example. JSBin, JSFiddle and the like are great online tools, but sometimes, I prefer my good ol' text editor on my machine. This was a great pretext to finally give a good go at Yeoman and see if it could help me automatically scaffold a few things here (that's what it's meant for after all).
My requirements where pretty limited (it was my first go with Yeoman after all):
- create an HTML, CSS and JS file with the appropriate
<script>tag to glue them together
- optionally include
jQueryif asked for
- have a Grunt build providing an Express server to host the projects file, and most importantly livereload
- create a Git repo, so I can tag specific steps in an example or just in case what started as an experiment finally grows bigger (I could probably have added a question for this)
This was already enough to get a nice overview of how Yeoman works and various features to build a generator.
A quick try ?
Curious and want to give the final a try? That can easily be arranged! You'll need node.js on your machine, one shell command (might need to
sudo), and that's about it for the installation:
$ npm install -g generator-playground
The generator relies on Yeoman (obviously), Grunt and Bower to work properly. They will get installed along if you don't have them already (yeah for the
peerDependencies property of
Once you've got the generator installed, head over to the folder you want to create the files in and go:
$ yo playground
This should have got you ready to hack: the project files have been created in the folder, and if you run
grunt server, the server hosting the project will star and your browser should open (a new tab, maybe)
A look under the hood
For those of you who made it back safely to the article and didn't get stuck hacking on the project they just generated, here comes the details on how things work (not necessarily in the order I got them to work).
Getting a project for a Yeoman generator started was really quick. Yeoman is a project to scaffold stuff, so they've got something to scaffold a Yeoman generator project:
generator-generator. A quick
yo commands later, I had a skeleton for my generator project.
Testing it out
Good code is tested code, and I didn't want the generator to escape this mantra. The generated project came with a couple of test samples in the
test folder. They where pretty handy to discover the helpers for running the generator from inside a test, simulating prompt answers or assert that files get copied properly.
The "Run the generator with a set of prompt answers and validate what comes out in the output folder" seemed to be a good enough strategy, as my generator didn't have too many options. Makes a nice little test suite that can be run by Travis CI.
Prompting the user
This is something I find really awesome: fancy command line prompts. Not just asking your user "Hey, what's your name?", but providing defaults, having different kind of prompts (command line checkboxes, anyone?)... I find this definitely more enjoyable than forcing your user to pass a heavy sequence arguments (though, you probably want to have both).
And it's even more enjoyable when your generator class already has that built in a handy
prompt() method. I didn't get to go too fancy for the playground generator, though, only a couple of yes/no questions were required.
Generating the project files
This is definitely the main task of a Yeoman generator: creating files, folders... The strategy here seems to be to have a
templates directory in your project, from which your generator will copy the files to whatever destination they're supposed to end up at (your generator has a handy
copy() method just for that).
Sometimes, you'll want to do a bit more than a plain copy, maybe include/exclude parts of the files according to the answers of the prompt(s). That's when the
template() method comes in. It uses your files as a template (underscore flavour, I think) for what will get in the destination file.
The git repository setup (creating a repo and making a first commit with the project files) was the occasion to play a bit with the async library to coordinate calls to the
git CLI. The massive one liner I had in mind apparently didn't cut it :(. This last step made the generator complete (at least for now).
Wrapping it up
Building this generator ended up being a great way to discover Yeoman and how it makes its scaffolding happen. Hopefully, I'll get to extend this first project with a few dream features I had to leave aside: support for preprocessor, CSS & JS linting or even getting rid of the dependency for grunt and bower (to scaffold project offline).
Thanks for reading this till the end, I hope you enjoyed it, learnt little tricks or maybe got ideas for your own Yeoman generator. Happy coding ;)