Running with Grunt
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.
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.