Getting started with Grunt, Bower, and Node.js

A 3 minute read written by Kyle September 11, 2014

Here at Yellow Pencil, we've been migrating to a Grunt/Bower/Node.js build management workflow for our front-end development.

This workflow can be intimidating at the beginning, but the initial challenges are worth it for these long-term benefits:

  • Easier development once you're set up
    • Your development file structure doesn't necessarily have to match up with the end result folder structure. This allows you to develop independent of potential restrictions in the end product folder structure.
  • Easier to manage distribution packages (dev vs. prod, etc.)
    • It’s very easy to have alternate configurations for both development and production (letting you minify only in production, for example)
  • More efficient minification and uglifying
    • Grunt allows you to minify/uglify and package all the content in a nice tidy bundle
  • Better automation of redundant tasks
    • Once you define how you want your files to be handled, everything can be automated through Grunt tasks. SASS, Minify, etc., will all be handled at once.

How to configure your new Grunt/Bower/Node.js setup

1. Install Node Package Manager and Node.js

First things first, you need to get Node.js installed, starting with npm. npm is the Node Package Manager, a utility that allows you to install the other important parts of this setup, Grunt and Bower.

To install Node.js, just go to http://nodejs.org/, click the install link and follow the directions.

2. Create the right folder structure

Once you have Node.js and npm available on your site path, you can install Grunt and Bower.

But before you can set up Grunt correctly, you need a folder structure that looks like this:

/MyFolder/app
/MyFolder/bower.json
/MyFolder/Gruntfile.js
/MyFolder/package.json

Hidden file:

/MyFolder/.bowerrc

.bowerrc

Let's go through these files one by one. We’ll start off with the simplest file in the bunch, the hidden file .bowerrc. This file tells Grunt that the Bower components, install when executing the install, should be placed here.

{
"directory": "app/bower_components"
}

The bower_components subfolder will be created automatically.

bower.json

Next let's look at the bower.json file. There are a few key components to this file, namely the ignore and dependencies section:

{
  "name": "yp-getting-started",
  "version": "1.0",
  "authors": [
    "Kyle Jeske <kyle@yellowpencil.com>"
  ],
  "description": "getting started kit",
  "moduleType": [
    "amd"
  ],
  "license": "MIT",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "jquery": "1.11.0",
    "modernizr": "~2.8.3" 
  }
}</kyle@yellowpencil.com>

 

package.json

Now let's explore the contents of the package.json. This file is used by the package manager to store dependencies that need to be installed for the project. This file will actually be responsible for the installation of Grunt itself.

{
  "name": "GettingStartedProject",
  "version": "0.0.1",
  "description": " ",
  "private": true,
  "author": "Kyle",
  "license": "MIT",  
  "dependencies": {},
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-clean": "~0.5.0",
    "grunt-contrib-concat": "~0.3.0",
    "grunt-contrib-copy": "~0.4.1",
    "grunt-contrib-uglify": "~0.2.4",
    "grunt-contrib-watch": "~0.5.3",
    "load-grunt-tasks": "~0.2.0",
    "time-grunt": "~0.2.3",
  },
  "engines": {
    "node": ">=0.8.0"
  }
}

Gruntfile.js

Finally, here's an example of the Gruntfile.js itself.
Here is the full file code:

// Generated on 2014-02-03 using generator-webapp 0.4.7
'use strict';

module.exports = function (grunt) {

    // Load grunt tasks automatically
    require('load-grunt-tasks')(grunt);

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    var options = {
        // Project settings
        paths: {
           // Configurable paths
           app: 'app',
           dist: 'dist'
        }	
    };

    // Define the configuration for all the tasks
    grunt.initConfig({
          clean  : {
		dist : {
		       files : [{
				dot : true,
				src : ['.tmp', '<%= paths.dist %>/*', '!<%= paths.dist %>/.git*']
			}]
		},
	},
        copy : {
		dist : {
			files : [ {
				expand : true,
				dot    : false,
				cwd    : '<%= paths.app %>',
				dest   : '<%= paths.dist %>',
				src    : [ '*.{ico,png,txt}', '.htaccess', 'images/{,*/}*.webp', '{,*/}*.html', 'styles/fonts/{,*/}*.*' ]
			}]
		},
		styles : {
			expand : true,
			dot    : false,
			cwd    : '<%= paths.app %>/styles',
			dest   : '.tmp/styles/',
			src    : '{,*/}*.css'
		}
	},

    });

    grunt.registerTask('build', [
        'clean:dist',
        'concat',
        'uglify',		
        'copy:dist'
    ]);

};

In the code snippet above, you can see we've defined 2 separate tasks: cleancopy. We also use the uglify and concat, default tasks to group and minify files in the project folder.

This is then registered as a task called build. Then enter the following command in your terminal:

grunt build

You can also run:

grunt -help

to see all the available tasks that you have installed with node.js

It executes these two tasks in sequence.

3. Install Grunt and Bower

Now that you have npm and the proper folder structure, installing Grunt and Bower is as easy as three lines of code. Make sure you're in the directory where package.json lives, and type the following:

npm install -g bower
npm install -g grunt-cli
npm install

The first two lines install both Bower as well as the Grunt command-line interface (which allows you to type ‘grunt build’). The third line installs any and all dependencies identified in your package.json file – yes, even Grunt itself.

And there you have it! You've configured your new Grunt/Bower/Node.js workflow.

Tune in next time when I'll go through how to set up your first project, and how to better manage your Grunt file.

If you have any questions about this configuration, be sure to email me.