Automation saves you time, your company money, and your employee’s sanity. At gskinner, we have a long history of building workflow tools to aid with anything from creating a simple button in Flash, to managing the build process for entire web apps or JavaScript libraries like CreateJS. Automation doesn’t need to be complicated. Some of my own tools only have a few lines of code, but those few lines can take hours off any project. For large scale projects spending hours or even days building an automation tool can have the same impact as a small tool. I generally start with a small scope (no more then a few hours) and see if what I’m building is a) Useful and b) Useable. If it doesn’t meet both of those criteria then I can re-evaluate my approach without burning too much time.
History
When we were primarily a Flash shop, using JSFL was almost a necessity. We built everything from simple scripts to custom panels, even turning an internal tool into the official Project Panel in Flash Pro. Our tools’ scope also extended to building desktop applications using Adobe AIR. We built tools for creating spriteheets (Zoe), editing language files, generating ASdocs, and even creating the install badge for AIR itself. Each of these tools were rooted in making our daily work lives more productive, efficient, and enjoyable.
When we entered into the world of JavaScript development, it presented its own, entirely new set of workflow challenges. We could no longer just hit “Ctrl + Enter” or press a green “Run” button and have our apps magically compile to SWFs. All of a sudden we had a long list of assets to manage, including:
- Combining and minifying JavaScript files
- Compiling Less & Sass files to CSS
- Managing assets like scripts, sounds, and images
- Creating page and component templates in html
- Deploying assets to a server
That’s a big list of items to manage, and without some sort of automation, it can be next to impossible for big projects.
JavaScript
For our first JavaScript projects, we used Google Closure to minify .js files. Closure requires developers to pass in their scripts on the command, along with some options to minify their code, which is tedious work when managing a lot of scripts. To make that easier, we wrote custom bash scripts to pass all the required scripts to the compiler, which worked ok, but not great. This setup required you to have a basic knowledge of shell scripting, and it would only run on Macs. Windows needed a .bat port. We then have 2 files to maintain, require java, and must ensure Google closure is set up correctly. This also requires a manual action to generate files, and doesn’t even touch on CSS or image management.
This was not a long term solution. For small projects it was barely passable, and large projects would become unmanageable, fast. When Adobe released Adobe AIR, it was possible for us to build custom desktop applications to help our workflows using tech we were familiar with. So we did exactly that, and built a custom AIR tool to organize JavaScript, and send them to Closure. This was much better, but not ideal since each developer required our tool and AIR installed. We had no way of watching for changes or sharing configurations, so for new devs to get started on a project it took time. Oh, and still no shared CSS or image management. We even experimented with using PHP to compile and minify JavaScript. That limited us even more though, since each person needed a server up and running, with the same configuration. Not a great solution for our workflow.
CSS
Less was our first option for a CSS precompiler. Less was great, compiling it was not. Each developer needed to run a separate app to compile the .less files, so we used things like CodeKit, or just manual command line tools to build the CSS files. Inevitably someone would forget to start the compiler, and nothing would look right, or someone else added files, that then needed to updated in the compiler or command line snippet individual developers used. Like JavaScript, we had server-side options for compiling CSS, but all the same pitfalls remained.
It was blatantly evident we needed to define a clear criteria for our automation environment:
- Cross-platform
- Flexible enough to minify JavaScript and compile Less files to CSS. Other tasks like compressing images and start development servers for testing started to become necessary as well.
- Quick and easy for new developers to get up and running.
This was about the time NodeJS was just starting to gain in popularity. Node’s success was, in no small part, aided by NPM. Having a massive library of JavaScript tools and frameworks at our fingertips was incredible. We began experimenting with custom Node scripts to start automating our build process, and one project even had all our JavaScript and CSS compiled and cached on the server. This was still not ideal: we needed a way for developers to work in isolation while using the exact same tools as everyone else. Then, we found an amazing build tool called Grunt.
Today
Grunt was the answer to all our build and automation needs, it was highly flexible, easy to set up, and cross-platform. Backed by npm’s huge repository of existing tools, developers began began writing custom plugins for Grunt. At the time of this writing, searching for “grunt” on npmjs.org yielded 11,322 results. That’s a lot to choose from. Grunt itself gets over 1 million downloads a month. The ecosystem is strong, and it’s showing no signs of slowing down.
Currently our default package.json file contains 19 different packages. One larger project has 28 pre-build tasks and 13 custom tasks. All these tasks can be configured once then run by a word or two:
grunt
grunt build
Amazing.
Another huge benefit of Grunt is one person can tweak settings in the GruntFile.js and those changes are propagated to every member of the team via Git. Even though running Grunt is relatively simple, we have a diverse team of designers and developers, all with varying levels of familiarity with the command line. When pushing updates, telling designers to run npm install
or sudo npm install;
could fall outside of their comfort zone. One of our projects even requires that you pass a variety of arguments to grunt, since we’re able to deploy builds in various configurations. To solve this, we have simple run.command or run.bat files included in project repositories, a simple double-click will update npm and start Grunt.
Grunt’s popularity is also aided by its inclusion in IDE’s like WebStorm, which we use a lot internally. Grunt files can be inspected, and tasks can be run with the click of a button.
Grunt Tasks
As mentioned, we use a wide variety of Grunt tasks to manage our workflows. Each project is unique, however a few favorite tasks/plugins are always used:
- grunt-contrib-sass or grunt-sass
Compiles our now preferred CSS pre-processor, Sass. We generally use grunt-contrib-sass for full sass support. More recently we’ve started using grunt-sass since the Sass compile times are much faster. - grunt-contrib-uglify
After closure, we switched to use uglify. It was faster, and had no dependencies other than Node. Also a JavaScript compressor written in JavaScript? How cool is that? - grunt-contrib-handlebars
Our preferred template system, logic-less, fast, and simple to use. - grunt-autoprefixer
Our projects are very CSS heavy and nobody likes to write browser prefixes, autoprefixer happily runs during a build making sure CSS is 100% cross-browser compatible. - grunt-throttle
Performance testing is crucial for any app, and grunt-throttle helps us test performance on slow connections. We run this process one port higher than the main one, so it’s a quick switch to run a throttled version of a site.
Future
Using these tools lets our developers and designers focus on what’s important: coding and designing awesome websites and applications. Not the nit-picky day-to-day repetitive tasks that come with web development. At gskinner we have a background in ActionScript and JavaScript so we chose to build tools in these languages. However it’s up to each team to know their core competencies and use what works for you. Languages like PHP, BASH, Ruby, Python, Java, will also get the job done.
Will Grunt be our tool of choice a year from now? 2 years? 5 years? I don’t know. I just know we will keep on using whatever tool suits our needs best. Whether that tool is using custom scripts in BASH, PHP, AIR , node or utilizing existing tools like Grunt or Gulp.
For more in-depth discussion on Grunt vs Gulp check out these 2 awesome posts:
What kind of automation tools do you integrate into your daily workflow?
We use a combination of `sbt` and `grunt`. In the future we might however move to `sbt` as these projects make that work:
https://github.com/sbt/sbt-web
https://github.com/sbt/sbt-js-engine
http://www.webjars.org/
The `sbt-extras` project allow you to setup `sbt` easily: https://github.com/paulp/sbt-extras
That said, `sbt` has a bit of a learning curve and we mainly use it for our Scala projects. The benefit is that it’s type safe.