Running with Grunt

Posted on by Kalon Hinds

This post is part of an ongoing series which will attempt to demonstrate and explain the Crunchinator. Each post will describe a different part of the technology behind the Crunchinator, and hopefully each will be useful as a stand-alone tutorial.

not this grunt While developing the Crunchinator’s frontend separately from its backend allowed for our developers to work asynchronously on different parts of the application stack, the front-end team now had a new issue to consider: “What is the best way to develop locally?”

In a normal situation, this question would not even need to be voiced. Most server-side frameworks come bundled with a lightweight development server in which engineers build their applications on. After some discussion and google searching we settled on using Grunt, a very powerful command-line tool which helps automate workflow.

What is Grunt?

Grunt is a javascript task-runner built on top of Node.js. This sounds pretty simple, however Grunt’s real power comes from its large selection of plugins and the ability for users to create their own tasks.

Let’s serve some files

Let’s say we have the following directory structure:

And we’d like to serve up the contents in our www folder, we can make a Grunt task to do just that. But before we get too deep into that, we need to get grunt on our system.

Grunt needs a Gruntfile and a package.json in order to be configured to work with a project. For those not familiar with npm, the package.json holds meta-data about a particular project. Such as, the project’s name, version, and dependencies.

After adding those files, our directory structure should look like this:

For this example, our package.json will look like so:

Run npm install to get the necessary dependencies onto your system. In our Gruntfile we’ll first encapsulate our configuration details and initialize an empty configuration object.

Next we’ll configure grunt-contrib-connect, our static server provider to serve the contents of www on port 8000:

Last but not least, we need to load the tasks provided by the grunt-contrib-connect plugin into our current context:

The final Gruntfile should look like this:

In your terminal type grunt connect to start your server.

How we used Grunt on the Crunchinator

The above example would not be used exactly as shown on an actual project, but it should serve as a decent introduction to Grunt. Now we’ll go over some of the ways we used Grunt when building the Crunchinator.

Setting an Environment

Various parts of our build script need to know whether we are running in a staging, testing, or production environment. This task allows us to set that information or change it in different parts of our build process. For example, in testing we always want to ensure we’re operating in our test environment, not any of the others:

Creating Angular Constants for Transient Settings

The Crunchinator’s front-end has several settings that the Angular needs to know about that wouldn’t be wise to hard-code into our app and store in version control such as the environment the application is currently running in, which API version we’re targeting, and our Bitly key for URL sharing. There is a Grunt plugin that generates angular constants, which is perfect for passing these settings to our application.

In grunt.initConfig we have:

The task is registered to ngconstant:configuration, which is run whenever we do a build, start our local server, or run tests.

Dealing with S3

We deploy the Crunchinator to S3 to eliminate various scaling issues and our deploy process is handled by Grunt using the grunt-s3 plugin. The settings look something like:

And a stripped down version of our deployment logic would look like this:

Hopefully this post shed some light on the power of Grunt and how it helped us while developing the Crunchinator. If you have any questions about anything covered in this post, please don’t hesitate to ask.

 
comments powered by Disqus