Using minified CSS and JavaScript files everywhere in SharePoint 2010

Find out how to leverage the extensibility capabilities of the SharePoint 2010 platform and support using minified CSS and JavaScript files everywhere.
Page Content

2011-11-27-UsingMinifiedCSS-01.jpg

In my previous post I showed you how you can automate minifying JavaScript and CSS files in Visual Studio 2010. As I also mentioned, SharePoint has limited support for using minified files. But just because something is not available out of the box doesn’t mean it’s not possible. Find out how to leverage the extensibility capabilities of the SharePoint 2010 platform and support using minified CSS and JavaScript files everywhere.

Minified files and the ScriptLink control

Using minified files is a great and easy technique for optimizing your SharePoint solution for performance. Out-of-the-box SharePoint 2010 provides the ScriptLink control which allows you to automatically switch between raw and minified versions of your files. However, it has two flaws. First of all it supports only JavaScript files and just as you can minify JavaScript files, you can also minify your CSS files. Another thing that you have to keep in mind, if you want to use the standard ScriptLink control with minified files, is that it works only for JavaScript files deployed to the LAYOUTS folder on the file system.

Using minified files everywhere

If you want to use minified CSS and JavaScript files everywhere you will need a solution other than the standard ScriptLink control. One solution that you could consider is creating a custom control that you would add to your Master Page and which would automatically switch between the raw and minified version of the asset file depending on the mode in which the Web Application is working. Such control could look as follows:

001 using System; 
002 using System.IO; 
003 using System.Web; 
004 using System.Web.UI; 
005 using Microsoft.SharePoint.Utilities; 
006   
007 namespace Mavention.SharePoint.Controls { 
008     public enum AssetType { 
009         CSS, 
010         JavaScript, 
011         Other 
012    
013   
014     public class AssetLinkControl : Control { 
015         public string Href { get; set; } 
016         public bool WithDebug { get; set; } 
017   
018         protected override void Render(HtmlTextWriter writer) { 
019             if (!String.IsNullOrEmpty(Href)) { 
020                 AssetType assetType = AssetType.Other; 
021                 string href = GetAssetUrl(Href, WithDebug, out assetType); 
022   
023                 switch (assetType) { 
024                     case AssetType.CSS: 
025                         RenderCssLink(href, writer); 
026                         break
027                     case AssetType.JavaScript: 
028                         RenderJsLink(href, writer); 
029                         break
030                
031            
032        
033   
034         public static string GetAssetUrl(string url, bool withDebug, out AssetType assetType) { 
035             string assetUrl = url; 
036             assetType = AssetType.Other; 
037   
038             if (!String.IsNullOrEmpty(assetUrl)) { 
039                 assetUrl = SPUtility.GetServerRelativeUrlFromPrefixedUrl(assetUrl); 
040                 assetType = GetAssetType(assetUrl); 
041   
042                 if (withDebug && HttpContext.Current.IsDebuggingEnabled) { 
043                     assetUrl = GetDebugUrl(assetUrl, assetType); 
044                
045            
046   
047             return assetUrl; 
048        
049   
050         private static AssetType GetAssetType(string url) { 
051             AssetType assetType = AssetType.Other; 
052   
053             if (!String.IsNullOrEmpty(url)) { 
054                 string extension = Path.GetExtension(url); 
055                 switch (extension) { 
056                     case ".css"
057                         assetType = AssetType.CSS; 
058                         break
059                     case ".js"
060                         assetType = AssetType.JavaScript; 
061                         break
062                
063            
064   
065             return assetType; 
066        
067   
068         private static string GetDebugUrl(string url, AssetType assetType) { 
069             string debugUrl = url; 
070   
071             if (!String.IsNullOrEmpty(debugUrl)) { 
072                 string extension = Path.GetExtension(debugUrl); 
073                 switch (assetType) { 
074                     case AssetType.CSS: 
075                         extension = ".css"
076                         break
077                     case AssetType.JavaScript: 
078                         extension = ".js"
079                         break
080                
081   
082                 debugUrl = String.Concat(debugUrl.Replace(extension, String.Format(".debug{0}", extension))); 
083            
084   
085             return debugUrl; 
086        
087   
088         private void RenderJsLink(string href, HtmlTextWriter writer) { 
089             writer.AddAttribute(HtmlTextWriterAttribute.Src, href); 
090             writer.RenderBeginTag(HtmlTextWriterTag.Script); 
091             writer.RenderEndTag(); 
092        
093   
094         private void RenderCssLink(string href, HtmlTextWriter writer) { 
095             writer.AddAttribute(HtmlTextWriterAttribute.Rel, "stylesheet"); 
096             writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css"); 
097             writer.AddAttribute(HtmlTextWriterAttribute.Href, href); 
098             writer.RenderBeginTag(HtmlTextWriterTag.Link); 
099             writer.RenderEndTag(); 
100        
101    
102 }

How it works

We start with retrieving the URL of the asset (line 21). To provide flexibility when defining URLs we first translate the URL to a server-relative URL by parsing tokens if applicable (line 39). Next we get the type of the asset that we are working with (line 40). While we could create two separate controls: one for CSS files and one for JavaScript files, in this sample we use one control for both types. The last step is to check whether the asset link points to an asset that is provided in two versions (raw and minified) and if the Web Application is in debug mode (line 42).

Using the WithDebug property allows us to use the AssetLinkControl both for referencing files that have already been minified (like the jQuery library) as well as files that we have created ourselves and that are available both as raw and minified files.

If the Web Application is in debug mode we convert the asset link to point to the debug version of the asset (line 43). Finally we return the URL and render it depending on the asset type (lines 23-30).

Using the AssetLinkControl

The AssetLinkControl can be used the best for declaratively registering assets in the Master Page and Page Layouts. To register an asset, all you have to do is to include the following snippet:

1 <Mavention:AssetLinkControl Href="~SiteCollection/Style Library/mavention/css/mavention.css" WithDebug="true" runat="server" />

Depending on the mode in which your Web Application is running, this control will either point to the minified or the debug version of the CSS file.

What the AssetLinkControl is not

Although the AssetLinkControl provides you with great flexibility, it is by no means a replacement for dynamically registering JavaScript or CSS files. The standard SharePoint 2010 CssRegistration and ScriptLink controls provide much more flexibility allowing you to determine how and when your assets should be loaded. Whenever you need to register a CSS or a JavaScript file on runtime you should use those standard controls instead. The great thing about how the AssetLinkControl is built, is that you can use its GetAssetUrl method to build a URL to your asset and then pass it to the standard SharePoint controls. This approach allows you to extend the standard functionality of the SharePoint platform with additional flexibility and optimization for performance.

Advertisements

1 Comment (+add yours?)

  1. MD
    Jul 21, 2015 @ 17:55:27

    Generally I don’t read article on blogs, however I would like to
    say that this write-up very forced me to try and do so!
    Your writing taste has been amazed me. Thank you, quite great post.

    Reply

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

%d bloggers like this: