Getting started with Grunt & Bower

Bower & Grunt

Lately I have been dabbling with various tools and libraries to improve my skills, and workflow. In the process I have tried Yeoman, which is a collection of tools and best practices to make web development easier and better.

Why Yeoman?

Yeoman comes with a collection of generators, which initialize your project with default set of tools and libraries those might be needed. But many a times, I fealt that one might not need all those tools, and such generators could be overload. Hence, its better to use basic building blocks of yeoman and create a workflow which suits you.

Introducing Grunt & Bower

In simple words Grunt is a JavaScript Task Runner. It lets you automate repetitive tasks like minification, compilation, unit testing, linting, etc.

On the other hand, Bower is a front-end package manager. It allows you to simple include, remove, upgrade various packages available for front-end development. You can see various packages available here.

Get Started

The best way to learn using grunt is with an example. So lets setup a simple web application with grunt and bower. I will be setting up a simple webapp that will include standalone development server, livereload, and compilation of less files.

Grunt

Grunt and Bower are based on node.js, so first install nodejs & npm on your machine. For information you can see node.js

To start with create a directory for your project, say gruntSample. Now your project needs a package.json and a Gruntfile.js. The package.json file is used by npm and should contain the dependencies for your project.
The Gruntfile.js will contain tasks and load Grunt plugins for you. Both of these files should be in the root of your project.

Package.json

You can find detailed information about creating package.json on grunt getting started guide. Here I’ll tell you the way I proceed.

From project directory run following commands.

npm init
npm install grunt grunt-contrib-less grunt-contrib-connect grunt-contrib-watch grunt-open matchdep connect-livereload --save-dev

npm init will guide you though various step in creating initial package.json file, you can go ahead with the default while creating it, and later change it manually.

Second command will install grunt and other grunt packages needed for this project.

Gruntfile.js

Now that we have added the package.json file, we can create Gruntfile.js. Here is the Gruntfile.js which we’ll be using in this sample project.

'use strict';
var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    grunt.initConfig({
        watch: {
            options: {
                nospawn: true
            },
            less: {
                files: ['app/styles/*.less'],
                tasks: ['less:server']
            },
            livereload: {
                options: {
                    livereload: LIVERELOAD_PORT
                },
                files: [
                    'app/*.html',
                    'app/styles/{,*/}*.css',
                    'app/scripts/{,*/}*.js',
                    'app/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
                ]
            }
        },
        connect: {
            options: {
                port: 9000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, 'app'),
                            lrSnippet
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        less: {
            server: {
                options: {
                    paths: ['app/components/bootstrap/less', 'app/styles']
                },
                files: {
                    'app/styles/main.css': 'app/styles/main.less'
                }
            }
        }
    });

    grunt.registerTask('server', function (target) {

        grunt.task.run([
            'less:server',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });
};

Bower

As already mentioned Bower is the package manager. So to get started you first have to install Bower. For this run following command in Terminal.

npm install -g bower

Then create a file named .bowerrc in project folder, with following content.

{
   "directory": "app/components"
}

This will direct bower to download bower components app/components directory.

Later run following commands.

mkdir app
mkdir app/components
bower init
bower install bootstrap

bower init will guide you to create a file bower.json. This is the file which will contain all the dependencies of the project. Later on production you can simply copy this file and run bower install to install all dependencies.

Project Files

Now lets add some code to test your project setup. Just create following files.

app/index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test Document</title>
    <link rel="stylesheet" type="text/css" href="styles/main.css">
</head>
<body>
    <h2>Hello Grunt!</h2>

    <script src="http://localhost:35729/livereload.js"></script>
</body>
</html>

app/styles/main.less

body{
    font-family: Arial, sans-serif;
}
h2{
    color: red;
}

In our Gruntfile.js we have added just one task to run the development server. This task will internally start a livereload server and will start compiling less to css as and when main.less file is changed.

Just run following command to test if everything is working fine.

grunt server

The command should start server and the should open http://localhost:9000/ in your browser. You can also try changing less / html file, the changes should be reflected on browser without refreshing the page.

Conclusion

In this grunt file we have just added support of compling less files, livereload and starting a development server. If you want you can also add various other tasks as per you requirement, more detailed tutorial can be found here.

I have also put up this sample grunt application on github, feel free to use it. gruntSample

Being a frontend developer if you haven’t yet added Grunt.js to your workflow, then you are seriously missing something. You should surely check it out.

3 Responses

  1. Will Vaughn #

    The part about yeoman being overload is exactly how I felt, I did exactly as you said, and broke out pieces using grunt until I felt comfortable with it.

    And then, I configured my own Yeoman generator to make my setup repeatable. It’s a pretty powerful feeling, and I wrote about it here http://projectpoppycock.com/roll-your-own-yeoman-generators/

    Reply
  2. Steve #

    Thanks for taking the time to publish this. Yeoman is certainly daunting when first engaging, and this quick, trimmed-down article really helped me get bower and grunt running for only what I needed. Just a quick and appreciative thanks!

    Reply
  3. Bjarne #

    Great article!
    You could also mention that you can use the –save argument for bower to update the dependencies in the bower.json file automagically. E.g. bower install bootstrap –save

    Reply

Leave a Reply