Sunday, June 12, 2011

Combine and minify JavaScript / CSS in Sitecore CMS

For a long time I tried to find a solid JavaScript / CSS combining and minifying solution, which is  easy to use, extensible and works with Sitecore without need to change sources, etc.
It’s not that hard to create own custom tool, but for many reasons it makes more sense to use actively developed and well-tested project.


And it looks like I’ve finally found it. With Combres (open source .NET library which enables minification, compression, combination, and caching of JavaScript and CSS resources) you can combine / minify both JS and CSS. You can even choose minification engine from: YUI Compressor for .NET, Microsoft Ajax Minifier and Google Closure Compiler. Also, Combres does the following stuff:
  • Adds Expires or Cache-Control header. Combres automatically emits Expires and Cache-Control response headers.
  • Gzip-s components. Combres will detect Gzip and/or Deflate support in the users' browser and apply the appropriate compression algorithm on each resource set's combined content before sending it to the browser. 
  • Configures ETags. Combres emits ETags for each resource set's combined content.
Another thing important for developers – you can simply turn off combining by changing configuration file, so you can debug JS without any problems. Read more about all Combres features here.

In this blog post I’ll describe installing Combres and configuring it to work with Sitecore website (AppPool - Integrated Mode and .NET Framework 3.5, minor adjustments will be needed if you use 4.0).
Configuring is a bit tricky, but I tried to describe all steps as clear as possible. This guide is based on official quick-start from here.

Download and install NuGet Package Manager extension for VS.NET 2010
  1. Backup your Web.config file (this is important!)
  2. Open your Sitecore project in VS.NET 2010
  3. Open the Package Manager Console (Tools > Library Package Manager > Package Manager Console)
  4. In the command window enter Install-Package Combres
The package manager may fail with “Unable to find assembly references that are compatible with the target framework '.NETFramework,Version=v3.5'.“ message, in this case you should change Target Framework property of the project to 4.0, install the package again and change it back to 3.5.

After the installation you’ll get few additional references in the project, App_Start folder, config files in  of App_Data folder, and updated Web.config.

Update Web.config
Combres installer cannot update Sitecore config properly. I suggest restoring the original one and performing the following steps:
  • Add configuration section declaration:
    <section name="combres" type="Combres.ConfigSectionSetting, Combres, Version=2.2, Culture=neutral, PublicKeyToken=1ca6b37997dd7536"/>
    
  • Add logger declaration (if needed):
    <logger name="Combres">
        <level value="DEBUG"/>
    </logger>
    
  • Add Combres configuration section (inside "configuration"):
    <combres definitionurl="~/App_Data/combres.xml" logprovider="Combres.Loggers.Log4NetLogger">
    
  • Add: “/combres.axd” to IgnoreUrlPrefixes
  • Add the following to the "pages" section:
    <namespaces>
        <add namespace="Combres"/>
    </namespaces>
    
  • Enable UrlRouting – add the following to the "modules" section of Web.config:
    "modules" section:
    <add name="RoutingModule" type="System.Web.Routing.UrlRoutingModule, 
                   System.Web.Routing, 
                   Version=3.5.0.0, Culture=neutral, 
                   PublicKeyToken=31bf3856ad364e35"/>
    "handlers" section:
    <add name="UrlRoutingHandler" path="UrlRouting.axd" precondition="integratedMode" type="System.Web.HttpForbiddenHandler, 
                   System.Web, Version=2.0.0.0, Culture=neutral, 
                   PublicKeyToken=b03f5f7f11d50a3a" verb="*"/>
    

Register Route (for ASP.NET 3.5 users)
  • Delete the generated file /AppStart/Combres.cs
  • Remove the reference to the assembly WebActivator
  • Open global.asax code-behind file 
  • Import Combres namespace, i.e. using Combres;
  • Add this to the first line of either RegisterRoutes() or Application_Start():  
    RouteTable.Routes.AddCombresRoute("Combres");
    
  • Reference “System.Web.Routing” library and set “Copy local” to true;
  • Rebuild your solution

Modify Combres.xml 
  • Open /App_Data/Combres.xml (this should be auto-created when you install the Combres NuGet package)
  • Add/remove resource sets, resources etc. as per your need. Here's the sample file:
    <resourceSet name="siteCss" type="css">
          <resource path="~/Css/default.css" />
        </resourceSet>
        <resourceSet name="siteJs" type="js">
          <resource path="~/Scripts/jquery-1.4.1.min.js" />
          <resource path="~/Scripts/jquery-1.4.1-vsdoc.js" />
        </resourceSet>
    
Add references to Combres resource sets in layout 
  • Open any page (for example, Sample layout.aspx) which need to reference JS/CSS resource sets defined in Combres.xml
  • Add the following to the "head" section:
    <%= WebExtensions.CombresLink("siteCss") %>
    <%= WebExtensions.CombresLink("siteJs") %>
    
If you have any questions, or encountered problems during the installation - do not hesitate to leave the comments. Also, it would be great if you can share your feedback or suggestions.