Minify, Combine CSS and JavaScript with Visual Studio
One of my personal favourites and easy to achieve page speed improvements, is to Minify and Combine CSS and JavaScript files upon building the release code.
Not everyone has continuous integration (CI) setup and able perform Combine and Minify actions after committing your code to a build agents; so I hope this will help a few people that are running locally or even with build agents.
The tools
- Microsoft Visual Studio Express 2010 (Download via Web platform installer)
- Microsoft Ajax Minified, YUI Compressor for .Net or Google Closure Compiler
- Large Coffee and a muffin
- Example JS, CSS files to work with.
- Web Deployment Project 2010
Lets get started by picking which minifier tool we’d like to use. Each of the minifies have their own merits and I would recommend you investigate further which is right for your needs. In this example we are going to be using Microsoft Ajax Minified and Web Deployment Project 2010. So download load them and install.
That was easy, lets move on to setting up a basic project and creating some simple CSS and JavaScript files.
We are going to start with a standard vanilla MVC (Model View Controller) .NET application install, good old “File > New Project > ASP.NET MVC Web Application”
Adding Web Deployment Project
Adding our basic Deployment Project. “Build > Add Web Deployment Project”
Release mode
We need to make sure we configure our new Web Deployment project in to Release mode.
Right click on “Solution ‘MinifyCombineCssJavaScript’ (2 projects)” and select “Properties”. In the new dialogue popup windows we need to change “MinifyCombineCssJavaScript.csproj_deploy” to release mode.
CSS and JavaScript files
Lets create a couple of new files in addition to the default ones that come with the vanilla MVC project; Extras.css and Extras.js. These new files really don’t do anything special, but you get the idea.
The beauty of these minify tools, means we can leave comments and formatting in our files and not worry about them still being there in the released code.
Extras.css
/* Style up our h1 */
h1
{
font-size:2.8em;
color:ff0000;
}
Extras.js
$(document).ready(function () {
$("h1").click(function () {
alert("Hello");
}); //End h1 click
}); //End of document ready
Time for a break
Again we have done some great ground work here, Time for a coffee and a muffin.
Done?
Right back to work.
Adding CSS and JavaScript files to our page
Lets edit the master page to allow site to use debug files when running locally and minified files when released.
Add this simple little code snippet to the Site.Master page to allow the magic to happen.
<%if (HttpContext.Current.IsDebuggingEnabled){%>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
<%}
else
{ %>
<!--release version here-->
<% } %>
Site.Master (original)
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">
<!--tml.RenderPartial("LogOnUserControl");--></div>
<div id="menucontainer">
<ul id="menu">
<li><%= Html.ActionLink("Home", "Index", "Home")%></li>
<li><%= Html.ActionLink("About", "About", "Home")%></li>
</ul>
</div>
</div>
<div id="main">
<div id="footer"></div>
</div>
</div>
Site.Master (new)
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
<%if (HttpContext.Current.IsDebuggingEnabled){%>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
<link href="../../Content/Extras.css" rel="stylesheet" type="text/css" />
<%}
else
{ %>
<link href="../../Content/all.min.css" rel="stylesheet" type="text/css"/>
<% } %>
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">
<% Html.RenderPartial("LogOnUserControl"); %>
</div>
<div id="menucontainer">
<ul id="menu">
<li><%= Html.ActionLink("Home", "Index", "Home")%></li>
<li><%= Html.ActionLink("About", "About", "Home")%></li>
</ul>
</div>
</div>
<div id="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
<div id="footer">
</div>
</div>
</div>
<%if (HttpContext.Current.IsDebuggingEnabled){%>
<script src="../../Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<script src="../../Scripts/Extras.js" type="text/javascript"></script>
<%}
else
{ %>
<script src="../../Scripts/all.min.js" type="text/javascript"></script>
<% } %>
</body>
</html>
Adding the Minify engine
Time to start editing the “MinifyCombineCssJavaScript.csproj_deploy” file.
Original “MinifyCombineCssJavaScript.csproj_deploy” file
<?xml version="1.0" encoding="utf-8"?>
<!--
Microsoft Visual Studio 2010 Web Deployment Project
http://go.microsoft.com/fwlink/?LinkID=104956
-->
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.30319</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{3740F659-35EC-4DF3-87A3-99FAC0D999F7}</ProjectGuid>
<SourceWebPhysicalPath>..\MinifyCombineCssJavaScript</SourceWebPhysicalPath>
<SourceWebProject>{B4BFD876-1C24-4A86-AD69-3ACD82E5DE12}|MinifyCombineCssJavaScript\MinifyCombineCssJavaScript.csproj</SourceWebProject>
<SourceWebVirtualPath>/MinifyCombineCssJavaScript.csproj</SourceWebVirtualPath>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>.\Debug</OutputPath>
<EnableUpdateable>true</EnableUpdateable>
<UseMerge>true</UseMerge>
<SingleAssemblyName>MinifyCombineCssJavaScript.csproj_deploy</SingleAssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>false</DebugSymbols>
<OutputPath>.\Release</OutputPath>
<EnableUpdateable>true</EnableUpdateable>
<UseMerge>true</UseMerge>
<SingleAssemblyName>MinifyCombineCssJavaScript.csproj_deploy</SingleAssemblyName>
</PropertyGroup>
<ItemGroup>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WebDeployment\v10.0\Microsoft.WebDeployment.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.WebDeployment.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="BeforeMerge">
</Target>
<Target Name="AfterMerge">
</Target>
<Target Name="AfterBuild">
</Target>
-->
Lets first add the Minify engine. We need to add the following line to just before “<Target Name=”BeforeBuild”></Target>”
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
Next we need to create a list group of CSS files which we wish to merge. We can do this in the “Aftermerge” target area.
<Target Name="AfterMerge">
<CssFilesIndex Include="$(TempBuildDir)\Content\Site.css;$(TempBuildDir)\Content\Extras.css;" />
</Target>
Now, we will also do the same for the JavaScript files.
<JsFiles Include="$(TempBuildDir)\Scripts\jquery-1.4.1.js;$(TempBuildDir)\Scripts\Extras.js;" />
Time to merge our CSS files in to one file and then for the JavaScript files.
CSS merge to all.css
<ReadLinesFromFile File="%(CssFiles.Identity)">
<Output TaskParameter="Lines" ItemName="cssLines" />
</ReadLinesFromFile>
<WriteLinesToFile File="$(TempBuildDir)\Content\all.css" Lines="@(cssLines)" Overwrite="true" />
JavaScript merge to all.js
<ReadLinesFromFile File="%(JsFiles.Identity)">
<Output TaskParameter="Lines" ItemName="jsLines" />
</ReadLinesFromFile>
<WriteLinesToFile File="$(TempBuildDir)\Scripts\all.js" Lines="@(JsLines)" Overwrite="true" />
We are on the final stretch.
Lets tell the minifier to compress our new single files. We’ll do this inside the “<Target Name=”AfterBuild”></Target>” and then delete out the single non-minified files, just so we keep things a little tidy.
<Target Name="AfterBuild">
<ItemGroup>
<JS Include="**\Scripts\all.js;" Exclude="**\*.min.js" />
</ItemGroup>
<ItemGroup>
<CSS Include="**\Content\all.css;" />
</ItemGroup>
<AjaxMin JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" CssSourceFiles="@(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
<ItemGroup>
<DeleteAfterBuild Include="$(OutputPath)Scripts\all.js" />
<DeleteAfterBuild Include="$(OutputPath)Scripts\jquery-1.4.1.js" />
<DeleteAfterBuild Include="$(OutputPath)Scripts\Extras.js" />
<DeleteAfterBuild Include="$(OutputPath)Content\all.css" />
<DeleteAfterBuild Include="$(OutputPath)Content\Site.css" />
<DeleteAfterBuild Include="$(OutputPath)Content\Extras.css" />
</ItemGroup>
</Target>
That’s it we are done, Hit F5 and watch the magic happen. The release version now knows to use the minified/combine files yet leaving our original files intact while working locally, allowing us to debug.
Finally
There is much more you can do with the build script, like excluding files not needed for your live site and deleting all other non live file. We could actually remove one of the steps above, however I thought I’d leave it in just to keep things in simple blocks.
The same process works for each of the different minifiers, it’s just a case of swapping them in and out to the one you prefer.
I hope this helps someone out, let me know.
If you found this helpful and would like to buy me a beer to say thanks, please 



Hi, great post.
I’m looking such a method to minify and combine.
However the website is kinda big and there are a lot of javascript files, each page includes their own set of those files. What i want to do is to minify and combine into several files which can be included on different pages. (as to stop loading javascript on the page that is totally irrelevant).
Is there any such a way? This is the best result i’ve came across so far; but not sure if there is anything standard about the problem described above.
Thanks in advance!
have a look at http://aboutcode.net/knapsack/ – recommended by Steve Sanderson
Was over complicated for me, but it might be just what you need….
RequestReduce provides a really nice solution for combining and minifying javascript and css at run time. It will also attempt to sprite your background images. It caches the processed files and serves them using custom ETags and far future headers. RequestReduce uses a response filter to transform the content so no code or configuration is needed for basic functionality. It can be configured to work in a web farm environment and sync content accross several servers and can be configured to point to a CDN. It can be downloaded at http://www.RequestReduce.com or from Visual Studio via Nuget. The source is available at https://github.com/mwrock/RequestReduce.