Integrating Grunt and Bower with Visual Studio 2013

For front-end development, node.js has already been, regardless you agree or not, in a main role for ages. It’s not only a development framework but also has become a development platform. It’s been natively supported by Visual Studio 2013. This post is not about node.js itself, but about development package manager and task manager, ie. Grunt and Bower. I will discuss how Visual Studio 2013 will be able to integrate with them.

Background

While I was doing an open-source website development project, a contributer responsible for front-end development started using Bower for LESS development. He showed me his works and asked me if I could directly use his repo without simply copying his compiled version of CSS files. After spending some times for research, Scott Hanselman‘s post, Introducing Gulp, Grunt, Bower, and npm support for Visual Studio would be used as my solution. However, it was not that easy as I expected, because:

  • I don’t have enough knowledge for them.
  • They don’t have enough documentation. Windows OS was not considered enough.
  • They are all CLI (command line interface) style, which I’m not used to.

Eventually I made it!

Prerequisites

Development Environment Setup

This is about integration of Visual Studio with other front-end development tools. Therefore it would be great to follow the setup in this order:

  1. Update Visual Studio 2013 Update 4
  2. Install/Update msysgit 1.9.5 (at the time of writing)

    *   Setup a proxy server, if necessary
    
  3. Install/Update node.js 0.10.35 (at the time of writing)
  4. Update npm

    *   Setup a proxy server, if necessary.
    
  5. Install Grunt
  6. Install Bower

    *   Setup a proxy server, if necessary.
    
  7. Install Gulp
  8. Install Visual Studio Extensions

Update Visual Studio 2013 Update 4

In Scott’s post, he advised us to update VS2013.3. But two months after his post, VS2013.4 was released. So, it would be great to update to 4.

Install/Update msysgit

If you use git on your Windows box, msysgit must have been already installed. It would be great to install the latest version of msysgit again with the option below:

As a default, Use Git Bash only was selected. But select the second option, Run Git from the Windows Command Prompt as this is necessary for using Bower integration with VS2013.

NOTE If you are behind a corporate firewall, you should setup proxy servers. The following commands help you setup the proxy server.

git config --global http.proxy "http://username:password@proxy.server:port"
`</pre>

For Active Directory users, try the following command. Make sure that backslash(`\`) should be encoded to `%5C`.

<pre>`git config --global http.proxy "http://domain%5Cusername:password@proxy.server:port"
`</pre>

Alternatively, you can directly modify the `%HOMEDRIVE%\.gitconfig` file like:

<pre>`[http]
    proxy = http://username:password@proxy.server:port
`</pre>

Or (For Active Directory)

<pre>`[http]
    proxy = http://domain%5Cusername:password@proxy.server:port
`</pre>

Setting up `HTTPS` connection is not necessary.

### Install/Update `node.js`

Install the latest version of `node.js`.

### Update `npm`

`npm (Node Package Manager)` is bundled with `node.js` installer. Open a Command Prompt Console as Administrator privilege and type the following to update `npm`.

<pre>`npm update -g npm
`</pre>

**NOTE** If you are behind a corporate firewall, you should setup proxy servers. The following commands help you setup the proxy server.

<pre>`npm config set proxy "http://username:password@proxy.server:port"
npm config set https-proxy "http://username:password@proxy.server:port"
`</pre>

For Active Directory users, try the following command. Make sure that backslash(`\`) should be encoded to `%5C`.

<pre>`npm config set proxy "http://domain%5Cusername:password@proxy.server:port"
npm config set https-proxy "http://domain%5Cusername:password@proxy.server:port"
`</pre>

Of course, you can directly modify `%USERPROFILE%\.npmrc` like:

<pre>`proxy="http://username:password@proxy.server:port"
https-proxy="http://username:password@proxy.server:port"
`</pre>

Or (For Active Directory)

<pre>`proxy="http://domain%5Cusername:password@proxy.server:port"
https-proxy="http://domain%5Cusername:password@proxy.server:port"
`</pre>

**FYI**: There are still many arguments on the community about using Active Directory. Some are successful, the others are not. Changing the double quotation marks (`"`) to the single quotation marks (`'`) can also be helpful to someones, not all.

### Install/Update `Grunt`

On the Command Prompt Console (as Administrator), try the following command:

<pre>`npm install -g grunt-cli
`</pre>

### Install/Update `Bower`

`Bower` needs `node.js`, `npm` and `git`. We have already installed them. Try the following command on the Command Prompt Console (Administrator mode).

<pre>`npm install -g bower
`</pre>

**NOTE** If you are behind a corporate firewall, you should setup proxy servers. The following commands help you setup the proxy server. This can be done by modifying `%USERPRIFILE%\.bowerrc`.

<pre>`{
    "proxy": "http://username:password@proxy.server:port",
    "https-proxy": "http://username:password@proxy.server:port"
}
`</pre>

Or (For Active Directory)

<pre>`{
    "proxy": "http://domain%5Cusername:password@proxy.server:port",
    "https-proxy": "http://domain%5Cusername:password@proxy.server:port"
}
`</pre>

### Install/Update `Gulp`

Install `Gulp` on the Command Prompt Console (Administrator mode) as well. This is just a requirements for the `Task Runner Express (TRX)` extension. We're not going further in this post.

<pre>`npm install -g gulp
`</pre>

### Install Visual Studio Extensions

Install the following extensions:
  • Task Runner Explorer
  • Grunt Launcher
  • Package Intellisense

    So far, we completed the development environment setup. Let’s move onto the actual source codes.

    Setup Grunt Tasks – gruntfile.js, package.json

    Both gruntfile.js and package.json are necessary for Grunt as they define how Grunt works. If you are joining an existing project, they might already exist, but if not, you should create both. There are many ways to create them. In this post, we are going to use grunt-init to create bare minimum gruntfile.js and package.json files.

    Install grunt-init

    grunt-init initialises/scaffolds the Grunt project. Open the Command Prompt Console and type the following:

    `npm install -g grunt-init
    `

    The following command shows you which templates can be used for scaffolding.

    `grunt-init --help
    `

    As you can see the image above, grunt-init-gruntfile is only available. Of course, this should be installed first, which will be explained in the following section.

    Install grunt-init-gruntfile Template

    grunt-init-gruntfile generates the very basic gruntfile.js and package.json as a bare minimum level. In order to use this template, follow the steps below:

  • Move the %USERPROFILE%\.grunt-init directory. If it doesn’t exist, create it.

  • Clone the repo from GitHub by running the following command. Alternatively, you can use TortoiseGit to clone it.

    `git clone --progress -v "https://github.com/gruntjs/grunt-init-gruntfile.git" "%USERPROFILE%.grunt-initgrunt-init-gruntfile"
    `
  • Run the following command at the root directory of your web app project.

    `grunt-init grunt-init-gruntfile
    `

    If you are asked some questions, use default settings.

    Generated gruntfile.js and package.json can be found on VS2013 like:

    Install npm Packages

    After including package.json, right-mouse click on the file.

    Click NPM install packages so that install modules defined in package.json. You can see the following screens. It’s a little bit strange that no message for completing installation pops up, by the way.

    Instead, on the Solution Explorer pane, you can confirm that all modules defined in package.json have been installed.

    Include gruntfile.js and right-mouse click on this file, and you can find both Task Runner Explorer and Grunt menus. Under the Grunt menu, you can also check the list of tasks defined in gruntfile.js

    Install Additional npm Packages – Bower and LESS

    If Bower is used and it imports LESS library, both should be included to Grunt. Bower can be added with grunt-bower-task.

    `npm install grunt-bower-task --save-dev
    `

    --save-dev enables the grunt-bower-task package to be listed on package.json. This option should be appended.

    Likewise, LESS package can be added with grunt-contrib-less.

    `npm install grunt-contrib-less --save-dev
    `

    Once both are installed, run npm install again to load both modules into the project.

    Add Tasks to GruntBower and LESS

    We have just added both Bower and LESS packages, but they are not still active. In order to get them enabled, modify gruntfile.js so that both are working properly.

    `grunt.loadNpmTasks('grunt-bower-task');
    grunt.loadNpmTasks('grunt-contrib-less');
    `

    Those two lines of code activate both modules. For initialisation, define settings within grunt.initConfig();.

    `bower: {
      install: {
        options: {
          targetDir: './lib',
          layout: 'byType',
          install: true,
          verbose: false,
          cleanTargetDir: false,
          cleanBowerDir: false,
          bowerOptions: {}
        }
      }
    }
    `

    This is the default settings for Bower. With this, Bower installs its dependencies into the /lib directory. Make sure that the value of targetDir can be anything but ./bower_components as ./bower_components is a default location and, actually, this module creates both /bower_components and /lib directories.

    `less: {
      development: {
        options: {
          paths: ["less"]
        },
        files: {
          "css/main.css": "less/main.less"
        }
      }
    }
    `

    This is the default settings for LESS. This compiles .less files defined in less/main.less stores the result into css/main.css

    Finally, setup Alias Task. This is a sort of batch job that allows multiple tasks in a defined order.

    `grunt.registerTask('build', ['bower', 'less']);
    `

    Save gruntfile.js and run Task Runner Explorer by right-mouse clicking the file on Solution Explorer.

    Grunt Build

    Any Bower project must contain bower.json as a meta data. Right-mouse click on bower.json and you can install Bower packages.

    Instead of doing this, we are going to use Grunt. Find the Task Runner Explorer (TRX) again.

    All tasks defined in gruntfile.js are displayed here. Right-mouse click on Alias Tasks &gt; build and choose Binding, and you will be able to select one of four statuses – Before Build, After Build, Clean and Solution Open – to run the build task. In general, the After Build is the best.

    Once the task is bound, double click the build task and you will be able to see the console running the task.

    NOTE If you see the #128 error, it’s because of the proxy server settings on git. Even though we have already set the proxy server at the global level, sometimes it doesn’t impact on the current project. In this case, setup the proxy server for the local repo level. For this, run the following command on the Command Prompt Console.

    `git config http.proxy “http://username:password@proxy.server:port

Alternatively, you can directly modify .git/config.

Once everything goes OK, you can see the files generated like above. This can be found on the Solution Explorer pane.

As stated earlier, grunt-bower-task generates both /bower_components and /lib, grunt-contrib-less compiles less/main.less file into css/main.css.

Conclusion

So far, we have discussed how Visual Studio can be integrated with Grunt and Bower. As each package manager has its own meta file – gruntfile.js, package.json and bower.json, they should be included within the project (or solution). On the other hand, interim directories like node_modues, bower_components and lib don’t have to be managed. With this approach, we can more easily manage front-end codes within Visual Studio. Of course Visual Studio 2015 will be more easy at handling this.