Home > Code Examples > Minify, Combine CSS and JavaScript with Visual Studio

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

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.

Ajax Minify 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”

File new project Default MVC screen

Adding Web Deployment Project

Adding our basic Deployment Project. “Build > Add Web Deployment Project”

Build, add web deployment project Build, Add web deployment project solution

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.

Web deployment 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

@ArranM

About these ads
  1. Masuramea
    June 22, 2011 at 8:18 am | #1

    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!

    • dave
      September 16, 2011 at 9:03 am | #2

      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….

      • November 20, 2011 at 3:46 am | #3

        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.

  1. August 10, 2010 at 12:49 pm | #1
  2. January 2, 2011 at 3:27 pm | #2
  3. April 13, 2014 at 10:20 pm | #3

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 333 other followers

%d bloggers like this: