I’m trying out Visual Studio (VS) 2015, which at the time of this writing, is in RC. Like most developers, the first thing I do with a shiny new VS is to install my tools and plugins. Of course I got Resharper (R#) installed and the PostFix Templates extension for R# installed.

 

Lately, I’ve been playing around with Win 8/10 JS apps that I’ve started in VS 2015, but I hadn’t opened any existing applications in VS 2015 since I work on some team projects. VS 2013 had one-way project upgrading and I had some issues with a previous team where not everyone was on the same version of VS.

 

Today, I had both VS 2013 and 2015 opened at the same time. This caused some issues with R#’s licensing platform so I made the leap and opened one of my web projects in VS 2015.

 

Let me back up a little: since I mostly do web development, I work with LESS quite a bit. Once upon a time I used a Post Build event to execute an npm command to compile my LESS files. As most web developers do, I have Web Essentials (WE) installed and at some point it finally stopped giving me issues with Bootstrap’s LESS files.

 

Moving forward: I had opened a web application in VS 15 and tried to save a LESS file. I noticed that it didn’t recompile the LESS file to CSS. That’s when I noticed that I had forgotten to install WE! Off to the VS Extension Manager! What’s this? WE installed and in this version, they’ve stripped the compilers out.

 

Which brings me to writing this post:

 

How to get Grunt to compile your LESS files on save, and at build, in VS 2015.

 

 

If you’re using an existing app or an app that isn’t using vNext you’ll want to start here. Otherwise you can skip the first step.

 

First, you’ll want to right click on the Web project -> Add -> Grunt and Bower to Project.

 

 

Once this is done, you’ll have two new files package.json and gruntfile.js. There’s lots of cool stuff you can do with Grunt but for this post we’re just going to talk about LESS.

 

Open package.json and add these items to your devDependencies

 

"grunt": "0.4.5",
"grunt-contrib-less": "^1.0.0",
"grunt-bower-task": "^0.4.0",
"less-plugin-autoprefix": "^1.4.0",
"grunt-contrib-uglify": "latest",
"grunt-contrib-watch": "latest"

 

grunt-contrib-less and less-plugin-autoprefix: are for compiling the LESS file(s) into CSS. You can probably do without autoprefix, but why would you do that?

grunt-contrib-uglify: this package will minify your LESS (and JS) into a compact CSS file.

grunt-contrib-watch: will let you create a task to monitor file changes and act on those changes. We’re going to use this to auto-compile our LESS to CSS any time we change our LESS files.

When you save this file, VS will automatically get and install the npm files to your project. You should have a hidden folder called node_modules with each of these packages in it.

 

Now open gruntfile.js and make it look like this:

 

/// <binding AfterBuild='less' ProjectOpened='watch' />
module.exports = function (grunt) {
    grunt.initConfig({
        bower: {
            install: {
                options: {
                    targetDir: 'wwwroot/lib',
                    layout: 'byComponent',
                    cleanTargetDir: false
                }
            }
        },
        watch: {
            less: {
                files: ['content/*.less'],
                tasks: ['less'],
                options: {
                    livereload: true
                }
            }
        },
        less: {
            production: {
                options: {
                    cleancss: true
                },
                files: {
                    "content/styles.min.css": 'content/styles.less'
                }
            },
            development: {
                options: {
                    paths: ['content']
                },
                files: {
                    "content/styles.css": 'content/styles.less'
                }
            }
        }
    });

    grunt.registerTask('default', ['bower:install']);

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

 

Let’s go over this.

At the top we have /// <binding AfterBuild='less' ProjectOpened='watch' />. These two can also be added with the Task Runner GUI (View -> Other Windows -> Task Runner [CTRL + ALT + \])

AfterBuild is all the tasks we want to run after the build event is finished.

 

watch: {
	less: {
		files: ['content/*.less'],
		tasks: ['less'],
		options: {
			livereload: true
		}
	}
},

 

This code is what makes the Task Runner keep an eye on changing files. 

 

I found out while writing this up, that the watch command uses a port and will not run while another project is open with a watch task using the default configuration.

 

Notice the tasks node, which calls the less task in the next section

 

less: {
	production: {
		options: {
			cleancss: true
		},
		files: {
			"content/styles.min.css": 'content/styles.less'
		}
	},
	development: {
		options: {
			paths: ['content']
		},
		files: {
			"content/styles.css": 'content/styles.less'
		}
	}
}

 

This is our less task. I have two sections defined. production: that gives us a minified version (using uglify) and development that compiles the LESS to CSS.

 

That’s basically it.

 

You can run Grunt tasks from the Package Manager Console, if you cd into project directory (where the gruntfile.js is) as grunt less or grunt less:production.

 

If you have npm and Grunt installed from the Node.js site, you can run these from command line as well, provided that npm is in your path.

 

This was just one of those annoyances when upgrading from one thing to another, but I’m glad to have found a solution. Take a moment with me to pause and mourn the loss of our Web Essentials compilers… 

I hope this post has been helpful to you. I appreciate any feedback or questions you have.