Thursday, January 2, 2014

Implementing Bundling and Minification with Sitecore Web Forms site

Bundling and Minification is introduced in .NET 4.5 with System.Web.Optimization namespace.

These new functionality can be implemented with .NET 4.0 as well.

Following are the steps to implement Bundling and Minification functionality with Sitecore Web Forms.

1. Dependencies
  • System.Web.Optimization.dll
  • WebGrease.dll
2. Defining Bundles

Method 1 - using RegisterBundles class method

using System.Web.Optimization;

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/bundles/css").Include(
                    "~/Styles/Site.css"));
        bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js"));
     }
}
 
Method 2 - using config file  (bundle.config) - Only static style bundles

<?xml version="1.0" encoding="utf-8" ?>
<bundles version="1.0">
  <styleBundle path="~/bundles/css">
    <include path="~/Styles/Site.css" />
  </styleBundle>
</bundles>


3. Register Bundles
Bundle registration can be done in two ways.
  • In the Application_Start method in Global.asax file
         RegisterBundles(BundleTable.Bundles);
  • As a custom pipeline processor in /Configuration/Sitecore/Pipelines/Initialization by editing web.config file
using System.Web.Optimization;
using Sitecore; 
using Sitecore.Pipelines;
 
namespace MyWebProject
{ 
  public class BundleConfig
  {
    [UsedImplicitly]
    public virtual void Process(PipelineArgs args)
    {
        RegisterBundles(BundleTable.Bundles);
    }
    public void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/bundles/css").Include(
                    "~/Styles/Site.css"));
        bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js"));
     }
  }
} 
Add follwing pipeline to /Configuration/Sitecore/Pipelines/Initialization as the final processor

<processor type="MyWebProject.BundleConfig, MyWebProject" />

4. Adding Namespace
Under the "/configuration/system.web/pages/namespaces" in web.config, add following namespace

<add namespace="System.Web.Optimization" />
 
5. Adding Bundles to View/Layout
In the main layout page in the head section, add style and script bundle virtual path references

<%: Scripts.Render("~/bundles/css") %> 
<%: Styles.Render("~/bundles/jquery") %> 

6. Allowing bundle virtual path urls to access files
"IgnoreUrlPrefixes" config setting in web.config file

<setting name="IgnoreUrlPrefixes" value="/sitecore/default.aspx|/trace.axd|/webresource.axd|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.DialogHandler.aspx|/sitecore/shell/applications/content manager/telerik.web.ui.dialoghandler.aspx|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.SpellCheckHandler.axd|/Telerik.Web.UI.WebResource.axd|/sitecore/admin/upgrade/|/layouts/testing|/bundles" />

7. Enable/Disable Minification
In the web.config file,  fine the "<compilation" tag and set "debug" property to "false" to enable bundling and minification.

Note: if you want to debug scripts and styles, setting debug="true" will ease the debugging process, since when debug="true", bundling and minification will not take place.

<compilation debug="false" targetFramework="4.0" />

Important Notes:
Best practice is to use include config file to do the config changes rather than doing it directly on web.config file


Update 1:
* Dependencies can be installed by importing the Microsoft.AspNet.Web.Optimization package.
* If the version is greater than or equal to 1.1 (1.1>=), then Styles.RenderFormat method is also available. This support the formating of the input html tag.
     Ex:  <link ref="stylesheet" type="text/css" media="screen" ..>

Limitations :
System.Web.Optimization mechanism does not convert relative image reference paths inside the .css file. Workaround will be to use Absolute path in image references inside .css files.


References
http://blogs.msdn.com/b/rickandy/archive/2012/08/14/adding-bundling-and-minification-to-web-forms.aspx
http://blog.vicreative.nl/2013/09/automatic-bundling-and-minification-in-net/
http://jockstothecore.com/bundling-with-sitecore-mvc/ 


2 comments:

  1. Thanks Chaturanga for sharing this.

    Well, you can fix the relative path issue using CssRewriteUrlTransform.

    ex.
    bundleTable.Add(new StyleBundle("~/mysite/styles/css")
    .Include("~/content/styles/jquery.ui.accordion.css", new CssRewriteUrlTransform()));

    ReplyDelete
  2. Thanks Chaturanga .
    We have a website running on Sitecore 7.1 (rev. 140324), implementing sitecore MVC 4.

    Bundling and minification is used as there are many css and less files. But sometimes website loose all the styling and there appears nothing in the bundling parameter (?v=), issue appearing intermittently.

    There is no exception logged in the Sitecore log files when this issue appears.The issue goes off when we recycle the app pool or restart the website.

    Can someone please let us know why the bundling is not working?

    It was first thought that this was due to performance, however on one occasion this occurred with very little load on the server.

    The link to the CSS bundle in the page source when working correctly looks like this:
    link href="/bundles/corp?v=PuOTrW8YgeGnD_UXCyNIhyui68_g4fo9fKY0QuHvxUM1" rel="stylesheet"/>

    When the error happens, the link looks like this (no value for the "v" parameter).
    link href="/bundles/corp?v=" rel="stylesheet"/>

    ReplyDelete