Optimizing ASP.Net Application – The Presentation Layer (Part 1)
Today I delivered a talk to the .Net developer community on optimizing ASP.Net applications. The talk was primarily focused on optimizing the presentation layer (HTML, JavaScript, CSS, …)
So how do we go about optimizing the presentation layer ? I am not gonna talk about View State or Session as it has been discussed all over the web time and again and by now people you would have already implement view state selectively and should be handling sessions with care and also implement GZIP compression over the session (Visit ASP.Net 4.0 enhancements if you are not doing this already).
When you request for any web page, there are two things which happens:
- The HTML (including data) is downloaded from the server
- All the other resources (JavaScript, CSS, Images, ..) gets downloaded from the server
Most of the times when you talk about optimizing your ASP.Net sites, you would look into things like how fast you could get the data from the database and how you could implement things like App Fabric Caching, etc.
What you miss out is the fact that almost 75 % of your page load time would be attributed to downloading and rendering the so called resources and not the actual HTML + data. At least that what the statistics says.
So what can you do about this ? First you need to understand what to fix. If you are using IE 9 as the browser, you can use the developer tools to understand how does your page statistics look like. I created a simple application which has an image control and some image thumbnails. You click on a thumbnail and it loads that image on the image control. All using a very simple JQuery. I ran the developer tools to see the network profile and I was shocked to see the results:
Alright I have a clear problem with my website and the high load time is because of my resources. Now what ?
Well go fix them. To help with this better, you could use Yahoo YSlow or Google Page Speed. Unfortunately you don’t have a version of these that will work with IE, so you would have to use Firefox or Chrome even though you know IE is the best browser .
Once you run this tool against your page, it would tell you what the issue is. Here are the major ones which will impact your performance greatly:
Location of CSS and JavaScript
One of the most common error I’ve seen in my career is that people conveniently include all their script references in the Head section. Well this is not a great practice. Always try and put then after the page’s UI content. Only CSS references should be provided in Head and not Script. If at all you don’t want to cut all those lines and put them down, use the defer property.
<script type="text/javascript" src="Scripts/jquery-1.4.1.min.js" defer="defer" />
<script type="text/javascript" src="Scripts/main.js" defer="defer" />
<script type="text/javascript" src="Scripts/modernizr-latest.js" defer="defer" />
The defer attribute specifies that the execution of a script should be deferred (delayed) until after the page has been loaded.
Add Expires Header
Always try and cache the local resources in the browser so you would not have to download them every single time. This can very easily be done for your ASP.Net application.
Jut go to web.config and add the following to <system.webServer>
<staticContent>
<clientCache httpExpires ="Fri, 29 Mar 2020 00:00:00 GMT"/>
</staticContent>
What happens is that all static content will now have an expires HTTP header set to the year 2020. Static content means anything that isn’t served through the ASP.NET engine such as images, script files and styles sheets.
Minimize the number of requests
Consider that your site has 15 JavaScript files including jQuery, Mordenizr or any other helpers as well and may be 10 style sheets. This alone would amount to 25 requests to your server effectively reducing the performance. How can this be helped. Obviously, you need to minimize the number of requests. But how on earth is this possible? simple, merge all style sheets into one and do the same with JavaScript.
You could write custom HttpHandlers to do this or you could use something already available like SquishIt
this lets you easily bundle some css and javascript so you can download one CSS and one JS instead of 10 – 15 of them independently. You would have to change the markup by commenting CSS and Script references and replacing them with something like this:
<%= SquishIt.Framework.Bundle.Css()
.Add("~/Styles/Site.css")
.Add("~/Styles/styles.css")
.Render("~/Styles/combined_#.css")
%>
and
<%= SquishIt.Framework.Bundle.JavaScript()
.Add("~/Scripts/jquery-1.4.1.js")
.Add("~/Scripts/main.js")
.Render("~/Scripts/combined_#.js")
%>
Minify CSS and Javascript
Another technique to reduce the load time on the client is to make sure that all your JS and CSS resources are minified. This allows you to reduce the size of your resources. One of the minifiers I have come across is the Microsoft Ajax Minifier. It’s a command line utility which also provides API so you can minify your resources at the time of deployment or even dynamically by using the API.
There are few other techniques which I will talk about in the next part of this post.
Happy Coding !!
Comments
Anonymous
October 18, 2011
Thanks for sharing your Knowladge.. Can you plz share the PPT or Recorded webex..Anonymous
October 20, 2011
Wouldn't it be better to use a max-age rather than a fixed expiry date? Otherwise, you'll have to remember to go back and update the expiry date every few years, or your site will stop caching. <staticContent> <!-- Approx. 10 years: --> <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="3652.00:00:00" /> </staticContent>Anonymous
November 07, 2011
The comment has been removedAnonymous
February 09, 2012
Hi, I got the below error while running the project. Can you please help ? Below is the error message : Attempt by security transparent method 'SquishIt.Framework.Utilities.FilePathMutexProvider.CreateSharableMutex(System.String)' to access security critical method 'System.Threading.Mutex..ctor(Boolean, System.String, Boolean ByRef, System.Security.AccessControl.MutexSecurity)' failed. Assembly 'SquishIt.Framework, Version=0.8.5.0, Culture=neutral, PublicKeyToken=null' is marked with the AllowPartiallyTrustedCallersAttribute, and uses the level 2 security transparency model. Level 2 transparency causes all methods in AllowPartiallyTrustedCallers assemblies to become security transparent by default, which may be the cause of this exception. Thanks Vikram