We are the Dev Teams of
  • brands
  • ebay_main
  • ebay
  • mobile
<
>
BLOG

How to use Grunt and Bower

by Frederik Leidloff

Grunt and Bower simplify a web developer's life. Bower as a package manager for web components and Grunt as a JavaScript task runner that automatically runs tasks like .less compiling, minifying or packing. 

For example at mobile.de we use bower for to include JavaScript libraries like jQuery or AngularJs. Grunt is used among other things to automatically compile .less files to css.

In this article, we will show you some code examples on how to use Grunt and Bower.

To start using Grunt and Bower, we will be writing a web application that uses jQuery and less. The web application will include livereload, so there is no need to refresh the browser at any time during development.

Prerequisites

Grunt and Bower are both based on node.js, so if not already installed, install node.js as well as the node package manager npm.

We recommend using n to install node.js and npm. “n” allows you to easily switch versions of npm and node.js. After installing it, there is only one command required to install node.js and npm:

n stable

Grunt

For our example project, we need 2 files: A package.json that contains all our dependencies for the web application and a Gruntfile.js that contains the tasks we want to execute on a regular basis like compressing, packing, less compiling or minifying.

Before starting with any configuration files, let’s install grunt with npm.

npm install -g grunt-cli

This will install the grunt command line tool globally for all projects. Notice that the global installation of grunt-cli must be done by a sudo user.

After that, we can start creating the package.json. To do that simply call npm init. You can leave the default values for now.

npm init

The result of this is a sort of standard package.json file. To use grunt in our project, we need to install it:

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

Let’s split up these commands and run through each one and explain how they work:

  • grunt: Installs the grunt files for this web app
  • grunt-contrib-less: For automatic less to css compiling
  • grunt-contrib-connect: Middleware plugin for serving files and browsing directories, etc.
  • grunt-contrib-watch: Watches files on your local filesystem for changes and runs specific tasks after a file changes
  • grunt-open: Opens urls from grunt
  • matchdep: Required to run the grunt server to start our app
  • connect-livereload: Reloads the web application automatically after files change
  • - -save-dev: The installed packages will only appear in your dev dependencies in the package.json file

After our package.json is complete, we can create a Gruntfile.js. This could be done using automated tools like Yeowman ; However, we will do this by hand. Copy the following to Gruntfile.js:

Gruntfile.js

'use strict';
var lrSnippet = require('connect-livereload')({port: 9000});
var mountFolder = function (connect, dir) {
  return connect.static(require('path').resolve(dir));
};
module.exports = function (grunt) {
  // load all grunt tasks
  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
  grunt.initConfig({
    watch: {
      less: {
        files: ['app/style/*.less'],
        tasks: ['less:server']
      },
      livereload: {
        options: {
           livereload: 9000
        },
        files: [
          'app/*.htm',
          'app/style/*.less',
          'app/script/*.js',
        ]
      }
    },
    connect: {
      options: {
        port: 8080,
        hostname: 'localhost'
      },
      livereload: {
        options: {
          middleware: function (connect) {
            return [
              mountFolder(connect, 'app'),
              lrSnippet
            ];
          }
        }
      }
    },
    open: {
      server: {
        path: 'http://localhost:<%= connect.options.port %>/index.htm'
      }
    },
    less: {
      server: {
        options: {
          paths: ['app/components/bootstrap/less', 'app/style']
        },
        files:{    
          'app/style/main.css': 'app/style/main.less' 
        }
      }
    }
  });
  grunt.registerTask('server', function (target) {
    grunt.task.run([
      'less:server',
      'connect:livereload',
      'open',
      'watch'
    ]);
  });
};

The Gruntfile.js looks more complicated than it actually is! To gain a better understanding of Grunt concepts, I will explain the most important lines in the following.

On line 10, the watch plugin is initialized. It watches all less files in app/style and automatically compiles them using the less task. Furthermore, the watch plugin watches .htm, .less and .js files (line 19) and reloads the web application when one of them changes.

On line 26, one can see the file server configuration using the connect plugin. The livereload plugin is also of interest and is configured on line 31. It allows automatic reloading of web applications.

After the server is started, grunt opens the web application using the default browser (line 42).
The less server that compiles less to css is defined on line 47. As mentioned before, it triggers whenever a less file changes.

Last but not least, tasks are defined that are executed after the grunt task is started on line 59.

Bower

After grunt is configured, let’s create our application.

We will use bower to include all the packages needed by our application automatically. This also enables us to easily update to newer versions.

Let’s start by installing Bower using npm:

npm install -g bower

This is a global install, so be aware that you will need sudo rights again.

In our small example project we are using jQuery, so let’s use bower to install jQuery. If you’re not sure what bower will use, a lookup command is available that tells you where bower is downloading the components. For jQuery, simply type

bower lookup jQuery

Great, that’s the repository we want. To install the components to our app. Create a folder called “app” go to the app folder using “cd app”. Then type

bower install jQuery

The installed components will be stored in bower_components/.

Project setup

At this stage the project setup is complete but we see that there is still no project. For our test project, we will use a classic Hello, world! application; a single web page that says “Hello, world!”.

Create the following two files:

app/index.htm

<!doctype html>
<html lang="en">
  <head>
    <title>Hello, Grunt and Bower</title>
    <link rel="stylesheet" type="text/css" href="style/main.css">
  </head>
  <body>
    <h2>Hello, World!</h2>
    <script src="http://localhost:9000/livereload.js"></script>
  </body>
</html>

app/style/main.less

h2 {
  color: red;
}

Now we can test our app! To start the server using grunt run:

grunt server

The default browser will open and you should see the Hello, World! text. Now, change your main.less, e.g. by changing the color of the H2 and your page will reload automatically. Our project should also make use of jQuery, so add the following to the end of the body of your index.htm (below the other script tag):

app/index.htm

...
<script src="/bower_components/jQuery/dist/jquery.min.js"></script>	
<script src="/script/main.js"></script>	
...

Then, create the main.js file:

app/script/main.js

$(function () {
  $('h2').addClass('modified');
});

Finally, add the modified css class to the main.less file:

app/style/main.less

.modified {
  &:hover {
    color: black;
  }
  text-decoration: underline;
}

We make use of less by using nested rules (&:hover) in the main.less.

Using jQuery, we injected the modified class. The web application should have been reloaded automatically, so “Hello, World!” is now underlined. Whenever you hover over text, it should change color to black.

Outlook

The application you just created is just the beginning. Grunt and Bower offers a wide range of  possibilities on how one can simplify typical frontend developer tasks.  A few things we do at mobile.de is automatic checking of our JavaScript style guides using jshint. That includes also getting our jshint rules from github and copying them to our projects using grunt.

I hope, you liked the blog post and find a few opportunities where grunt and bower can help make your life easier.

?>