I’ve been working on a new open-source project lately. To be honest, I’ve been so busy coding that I haven’t had time to write about it, but since everyone at Bocoup got together the other day and told me I had to write a blog post—apparently they’re pretty excited—I’d like to introduce grunt.
What is grunt?
Why did I create grunt?
It’s far too easy to create a gist or one-file repo and promise yourself that you’ll add linting and unit tests later. With grunt, all the excuses you’ve ever made just disappear. Instead of being a chore, creating a new project and performing repetitive but necessary tasks such as linting, unit testing, concatenating and minifying files become trivially easy.
In the end, I realized that a task-based build tool with built-in, commonly used tasks was the approach that would work best for me. Unfortunately, I couldn’t find a build tool that worked the way that I wanted. So I built one.
How did I create grunt?
Just install it with
npm install -g grunt and see for yourself.
As of now, grunt has the following predefined tasks that you can use in your project:
- concat – Concatenate files.
- init – Generate project scaffolding from a predefined template.
- lint – Validate files with JSHint.
- min – Minify files with UglifyJS.
- qunit – Run QUnit unit tests in a headless PhantomJS instance.
- server – Start a static web server.
- test – Run unit tests with nodeunit.
- watch – Run predefined tasks whenever watched files change.
In addition to the built-in tasks, you can create your own tasks. Don’t like a built-in task’s default behavior? Override it. Check out the grunt API documentation and the built-in tasks source for everything you need to know about creating custom tasks.
Also, creating a grunt plugin allows you to package related tasks into an easily-installed npm module. Backbone Boilerplate is a good example of a grunt plugin. If you’ve developed a grunt plugin, let me know by telling me in the issues tracker.
Initializing a new project
This might be my favorite grunt feature. The init task initializes a new project, based on the current environment and the answers to a few questions. Once complete, a grunt.js configuration file will be generated along with a complete directory structure, including a basic readme, license, package.json, sample source files and unit tests (etc). The exact files and contents created depend on the template chosen along with the answers to the questions asked.
Now, instead of sketching out an idea in a quick one-off gist, I can create the scaffolding for an entire project in about 10 seconds, “fill in the blanks,” and then run grunt to lint, test, concat and minify my code. If everything passes, I can then commit and push my code. And anyone who wants to contribute to the project can install grunt and do the same.
There are currently a handful of built-in init templates, including a “jquery” template that has been designed to create a basic jQuery plugin compatible with the upcoming jQuery plugins site, and a generic “gruntfile” template that can be used to very quickly add a grunt.js gruntfile to an existing project. You can override init template files if you want to customize a built-in init template or create your own. And your templates don’t need to be grunt-related. You could create an init template that builds out models or views or package.json files—whatever you need.
If you want to try the init task, cd to an empty directory, run the command
grunt init:jquery (assuming grunt is already installed) and follow the on-screen prompts. When grunt is done creating files, poke around. Run
grunt. See what happens.
Actually using grunt
If you like “action shots,” here’s an example of grunt, grunting grunt:
BTW, if you like my bash prompt, it’s available in my dotfiles repo.
Grunt in action
We’ve already been using grunt at Bocoup. Rick Waldron used grunt to build the Ringmark mobile test suite. He, Scott González and Jörn Zaefferer have been working on replacing all the jQuery project (jQuery, jQuery UI and QUnit) build tasks with grunt. Tim Branyen has created the Backbone Boilerplate grunt plugin. Mickael Daniel is working hard to create a grunt plugin for HTML5 Boilerplate. And I’ve been using grunt to initialize and build every new project I work on.
Grunt is currently in beta. While we’re already using it on multiple projects, it might have a minor issue or two. The API has gone through multiple iterations, and is considered stable, but there is a possibility that it will change in the future, based on your feedback.
I encourage you to try grunt out in your projects. If you’re interested in creating grunt tasks or a grunt plugin, or just want to discuss grunt, join the irc.freenode.net #grunt IRC channel. And by all means make suggestions or report bugs!
I have a lot of excellent features planned for grunt. I want to further evolve the API to help make grunt as flexible and powerful as possible. I want to find a way to make the creation and discovery of grunt tasks and plugins easier. And I want to create more built-in tasks and init templates.
Good luck, and happy grunting!