Grunt your ASP.net builds
Visual Studio 2013 has made great strides at being a great tool for web development. When combined with the webessentials package it is actually a very good tool, maybe the best tool out there. However it has one shortcoming in my mind and that is the poor support for third party tools. It is difficult to track the latest trends in web development when you’re working on a yearly release cycle, as Visual Studio does. This is somewhat ameliorated by the rapid release of plugins and extensions. Still I think think that the real innovative development is happening in the nodejs community.
Ideally your development environment mirrors your production environment exactly. However time and financial constraints make that largely impossible. If production is a hundred servers there is just no reasonable way to get a hundred servers for each developer to work on all the time. Unless your company has pots of money
Visual Studio falls down because when you F5 a project the environment into which you’re placed is not the same as the package which is generated by an upload to your hosting provider. It is close but there are some differences such as
- files which are not included in the project but are on disk will be missing in the package
- CSS files are similarly not minified or combined
These actions can be breaking changes which will not be apparent in the development environment. For instance changing the names of function arguments, as is common in minification, tends to break AngularJS’ injection.
Thus I actually suggest that you use Grunt instead of the built in minification in ASP.net. Let’s see how to do exactly that.
The first thing you’ll need is a copy of nodejs. This can simply be the copy which is installed on all your developer workstations and build server or it can be a version checked into source control(check in vs. install is a bit of a holy war and I won’t get into it in this post). If you’re going to check a copy of node in then you might want to look at minimizing the footprint of what you check in. It is very easy with node to install a lot of packages you don’t actually need. To isolate your packages to your current build then you can simply create a “node_modules” directory. npm, the package management system used by node, will recurse upwards to find a directory called node_modules and install to that directory.
Let’s assume that you have node installed in a tools directory at the root of your project, next to the solution file, for the purposes of this post. In there create an empty node_modules directory
Now that node is in place you can install grunt and any specific grunt tasks you need. I have a separate install of node on this machine which includes npm so I don’t need to put a copy in node_modules. I would like to have grunt in the modules directory, though.
npm install grunt
npm install grunt-contrib-uglify npm install grunt-contrib-concat npm install grunt-data-uri
Now we will need a gruntfile to actually run the tasks. I played around a bit with where to put the gruntfile and I actually found that the most reliable location was next to the node executable. Because grunt and really node in general are more focused around convention over configuration we sometimes need to do things which seem like hacks. The basic gruntfile I created looked like
Now we need to run this grunt process as part of the build. As I mentioned this is a bit convoluted because of convention and also because we’re choosing to use a locally installed grunt and node instead of the global versions.
First we create a runGrunt.bat file. This is what visual studio will call as part of the post build.
Then tie this into the msbuild process. This can be done by editing the .csproj/.vsproj file or by adding it using Visual Studio
The final step is to create a wrapper for grunt as we don’t have the globally registered grunt
Best of luck using node to improve your ASP.net builds!