Browse Tag: nodejs

Grunt in Visual Studio

This post walks through the basics of using Grunt in Visual Studio 2013.  Specifically, we will add two compile time tasks; one for linting TypeScript files, and another for linting SCSS.  You are not limited to using just linters with Grunt, in fact you can do just about anything.

Grunt is specifically good at running repetitive tasks and is widely used in the non-.NET world via the command line.  Other common tasks include; minification, compilation and running unit tests.  Fortunately for us, some unofficial tools have been developed by Microsoft (specifically, the awesome Mads Kristensen and his dedicated team) which enable us to use Grunt directly inside Visual Studio.

Grunt is JavaScript configuration based, meaning you configure Grunt via a special file called GruntFile.js, which you add to your project.

This post specifically targets Visual Studio, because at the time of writing Visual Studio hasn’t been released yet (its actually RC at this point).  As Microsoft tooling is evolving rapidly at this time, i’ll avoid covering 2015 for now (however, I may revise this post after Visual Studio 2015 is released).


NodeJS and npm

Grunt is built on top NodeJS and is installed via the Node Package Manager (npm).  Both of these tools need to be installed to use Grunt.  Check that you already have NodeJS installed, and/or download the latest version.  The installation is a trivial process, so I wont document it fully here, but please ensure that the “npm package manager” feature is installed.  This feature is selected by default, and it is need to install Grunt (and indeed, any other package).



Before we can use Grunt, we must install it globally.

Open a command prompt and type

npm update -g npm

As advised by the product documentation, this ensures that you’ve got the latest version of npm before continuing.  Now, run the following command;

npm install -g grunt-cli

You might want to get reacquainted with running commands in this way because with the rapid state of change in the industry, development of visual tools is always going to lag behind (even with Microsoft’s new rapid development and deployment ethos, but that’s a whole other discussion).


Task Runner Explorer

This tool will run our Grunt tasks for us.  It will parse our Grunt File (which we will create shortly), list our tasks, let us run our tasks individually, and let us bind our tasks to “IDE events” (pre-build, after build, clean & solution open).

To install Task Runner Explorer, go to Tools > Extensions and Updates and type Task Runner Explorer.  The first result should by created by Microsoft Corp.

Task Runner Explorer
Task Runner Explorer

Local Grunt

Now that we have the necessary tooling installed, we need to add Grunt to our actual project (and any additional packages we want to use).  Packages are controlled using a special file called package.json.  This file contains metadata about your project, and the packages its dependent on (and potentially a bunch of other stuff that is out of the scope of this tutorial).

Create a file called package.json at the root of your project, and add the following code;

    "name": "Grunt101",
    "version": "1.0.0",
    "description": "Grunt101",
    "author": "Jon Preece",
    "devDependencies": {
        "grunt": "~0.4.5",
        "grunt-tslint": "~2.3.1-beta",
        "grunt-scss-lint": "~0.3.6"

The file is pretty self explanatory, but if you want a little more information with regards to versioning, see this useful post; Node and npm Version Numbering: Guide and Best Practices.

To save time later, I’ve also included the other development dependencies.  In this case, our TypeScript linter (TSLint) and SCSS linter (scss-lint).  We will configure these shortly.

To install the dependencies, open a command prompt and change the directory to that which contains your newly created package.json and run the following command;

npm install

This will result in a new directory being created, called node_modules, which will contain each dependency.

npm install
npm install


As previously mentioned, Grunt is a JavaScript based task runner.  Grunt is configured/controlled using a file called Gruntfile.js.  This file is responsible for defining the configuration for each task, loading the npm tasks, and registering the tasks.  You can have many tasks and many aliased groups that run multiple tasks.

For this tutorial we are going to validate our TypeScript and SCSS code quality using linters.  Specifically, Grunt has packages called Grunt-TSLint and Grunt-SCSS-Lint (you defined and installed these packages earlier).

Add the following configuration;

module.exports = function (grunt) {
    'use strict';

        scsslint: {
            allFiles: [
        tslint: {
            options: {
                configuration: grunt.file.readJSON("tslint.json")
            files: {
                src: ['*.ts']


    grunt.registerTask('default', ['scsslint', 'tslint']);

Again, the beauty of Node and Grunt especially is that its pretty simple to understand what’s going on, even for a beginner.

SCSS Lint Task

The minimum configuration required is the path to your SCSS files, using the property allFiles.  In the given file, we just look at the root directory of our application for SCSS files, but you can make this more complicated, and recursive, as follows;


There’s a comprehensive tutorial on how to customize this further to meet your needs over on

TS Lint Task

Before you can lint a TypeScript file, you must define some rules that you want to enforce throughout your code-base.  You can push this configuration to source control and share with your team for maximum consistency.

If you have Web Essentials installed (and I highly recommend all web developers install this excellent tool) then you can quickly generate a configuration file by clicking Web Essentials > Edit Global TSLint Settings (tslint.json).  Clicking this drops a tslint.json file into your Documents folder and opens it directly in Visual Studio, where you can make edits.  I highly recommend closing the file, moving it into your solution folder, and adding it as part of your project for easy access later.

If you don’t use Web Essentials are you insane? you can grab a sample configuration file directly from the GitHub source code repository and again I recommend that you add it as part of your project.  I won’t go into the ins and outs of each of the TypeScript linting rules, that’s for another time.  Just know that you can change them to your hearts content.

The files property works exactly the same as for the SCSS linter.  You pass in a string that represents the path of your TypeScript files.


Final Steps

Add some code

There’s just one more step we need to take before running our tasks, we need some code to test!

Add a new SCSS file to your project, and a new TypeScript file.  Add the following beautifully written ugly code to the TypeScript file;

module SomeModule {

    export class SomeClass {

        str: string;

        constructor() {
            this["str"] = "Hello, World"

The main issues with this code are trailing whitespace, no "use strict", missing semi-colons and access to a property via a string literal.  We will let Grunt tell us about these shortly.

Open the task runner

Open the task runner by going to View > Other Windows > Task Runner Explorer.

Select your project (if it isn’t selected by default) and click the refresh button.  Your Gruntfile.js configuration file should be loaded and the alias tasks and individual tasks should be displayed.

You can manually run a task (or set of tasks) by right clicking and selecting Run.  If all went well, you should see the following output;

C:\Users\Jon\Documents\Visual Studio 2013\Projects\Grunt101> cmd.exe /c grunt -b "C:\Users\Jon\Documents\Visual Studio 2013\Projects\Grunt101" --gruntfile "C:\Users\Jon\Documents\Visual Studio 2013\Projects\Grunt101\gruntfile.js" default
Running "scsslint:allFiles" (scsslint) task
Running scss-lint on allFiles
>> 1 file is lint free
Running "tslint:files" (tslint) task
>> app.ts[14, 3]: file should end with a newline
>> app.ts[9, 19]: object access via string literals is disallowed
>> app.ts[1, 1]: trailing whitespace
>> app.ts[3, 1]: trailing whitespace
>> app.ts[5, 1]: trailing whitespace
>> app.ts[9, 42]: missing semicolon
>> app.ts[2, 2]: missing 'use strict'
>> 7 errors in 1 file
Warning: Task "tslint:files" failed. Use --force to continue.
Aborted due to warnings.
Process terminated with code 3.

Success! Wait what? Oh yes, the task has failed because our TypeScript file has lots of linting errors.  Open up the TypeScript file and use the output message to fix each problem.  Once done re-run the task again by right clicking and clicking run.  Once all issues are resolved, you should get the following;

C:\Users\Jon\Documents\Visual Studio 2013\Projects\Grunt101> cmd.exe /c grunt -b "C:\Users\Jon\Documents\Visual Studio 2013\Projects\Grunt101" --gruntfile "C:\Users\Jon\Documents\Visual Studio 2013\Projects\Grunt101\gruntfile.js" default
Running "scsslint:allFiles" (scsslint) task
Running scss-lint on allFiles
>> 1 file is lint free
Running "tslint:files" (tslint) task
>> 1 file lint free.
Done, without errors.
Process terminated with code 0.


Right clicking and clicking run is a little too manual for my liking, this is an automation tool isn’t it? Alas, the Task Runner Explorer provides you with Bindings.  Basically you can hook in to events in the IDE and run your tasks automatically when one of events happens.

Available bindings;

  • Before Build
  • After Build
  • Clean
  • Solution Open

To bind a task to a binding, right click the task (or again, the aliased task) and select Bindings > {An IDE Event of your choice}.  In my case, I’ve chosen Before Build.  So when I press Ctrl+Shift+B the tasks are ran automatically.

Note that as far as I know, you can’t fail the build if a task fails at this point.  No doubt this is an upcoming feature.


Grunt is a brave new world for most .NET developers.  Tooling is certainly in its infancy (within Visual Studio) at this point, but the awesome power of NodeJS, npm and Grunt can be harnessed with some useful extensions.