It’s been 7 months since the last post in my YSlow series. So why did I stop blogging about performance optimization? Well actually there are two answers to that question. First on is my passion for unit-testing which I started blogging about at pretty much that time. Secondly I have to admit, that I didn’t know what to write about YSlow rule #13 – Remove Duplicate Scripts.

So what’s the problem with including the same JavaScript twice (or more)? When the browser reaches a script import it makes a HTTP request for that script. Not all browsers are smart enough to catch this mistake. Even with modern and fast internet connections, making a lot of requests, slow down the experience of your website. If you have your caching strategy under control the duplicate request shouldn’t be much of a problem but if not, the remote request is actually made multiple times. I typically see two different patterns when people by accident include the same script twice.

Pattern 1: Including scripts i both layout/master page and partial views

Partial views in ASP.NET MVC are a great way to extract common reusable controls into a single file. A partial view has the possibility to load external JavaScript files as well. A common mistake by web developers, is to include a reference to the same script in both the layout/master page-file as well as a partial view. I haven’t really found a great solution to catch this mistake, other than running YSlow on your page. If you read this and know a solution to this problem, please let me know in the comments.

Pattern 2: Including both minified and unminified version of a script

I’ve seen multiple websites doing something like this:


<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

You typically see this pattern from webdev-cowboys needing to track down some bug in the JavaScript by adding the unminified version of jQuery to be able to debug it. When the bug is fixed, they forget to remove the newly added reference. The mistake won’t show itself in the browser, because the last imported script override the first. I was a bit disapointed by the new bundling support in ASP.NET MVC 4 when I found out, that the bundler always adds the minified version if available. Making it chose the full version in Debug configuration and the minified version in Release configuration would have been the optimal choice for me.

I’m working to catch this bug in my upcoming website validator HippoValidator.com.

I sometimes find myself doing extension methods for the HtmlHelper class in ASP.NET MVC. I like HtmlHelper but don’t really dig when the methods generate HTML. This is what partial views are for, right? I usually add small utility methods related to a single view on the view model, but when dealing with shared methods, the HtmlHelper seems like the best choice.

Extension methods in general are pretty easy to unit-test, due to the fact that they are just static methods. But extension methods on HtmlHelper have all kinds of information available through the “this HtmlHelper”-parameter, which can make these methods extremely hard to test. This is the helper method I use to create a new instance of the HtmlHelper class:

public HtmlHelper<T> CreateHtmlHelper<T>(ViewDataDictionary viewData)
{
    var cc = new Mock<ControllerContext>(
        new Mock<HttpContextBase>().Object,
        new RouteData(),
        new Mock<ControllerBase>().Object);

    var mockViewContext = new Mock<ViewContext>(
        cc.Object,
        new Mock<IView>().Object,
        viewData,
        new TempDataDictionary(),
        TextWriter.Null);

    var mockViewDataContainer = new Mock<IViewDataContainer>();

    mockViewDataContainer.Setup(v => v.ViewData).Returns(viewData);

    return new HtmlHelper<T>(
        mockViewContext.Object, mockViewDataContainer.Object);
}

The method uses Moq to create mock objects for various ASP.NET MVC classes, but can easily be ported to Rhino Mocks or other mocking frameworks. Testing extension methods on HtmlHelper is now piece of pie. In the following example I test an imaginary extension method named SplitModel using the CreateHtmlHelper-method:

[Test]
public void CanSplitString()
{
    // Arrange
    var htmlHelper =
        CreateHtmlHelper<string>(
            new ViewDataDictionary("Hello World"));

    // Act
    string[] result = htmlHelper.SplitModel();

    // Assert
    Assert.That(result.Length, Is.EqualTo(2));
}

A former college of mine told me, that he had founded “The association opposed the abandonment of PerformanceDude.com”. In order to make him happy, I thought that I would leave the wonderful world of unit testing for a moment, in the benefit of writing a performance related post :)  We’ve reached YSlow rule number 12 – Avoid redirects. I think the Yahoo documentation about the subject is a bit vague, so here’s my opinion on the subject.

Redirects are used to tell the browser, that a requested URL have been moved either permanent (http status code 301) or temporarily (http status code 302). When doing a request which returns a 301/302, the browser automatically makes a new http request, towards the URL returned by the 301/302. Being able to redirect URLs is really important if you want to change your URLs and your site is already indexed by search engines. If changing your URL scheme without returning a redirect, you basically lose your ranking in search engines like Google and all those hours spend getting link juice is wasted. In ASP.NET MVC 3 doing redirect is easy:

public ActionResult OldUrl()
{
    return RedirectPermanent("/the-new-url");
}

Notice that the above example returns a 301 (permanent redirect). If you for some reason need to return a 302, use the Redirect-method instead.

So what is my opinion on this YSlow rule? Well unless you use some sort of obscure web-framework which does a lot of magic behind the scene, there’s only one pitfall which should make you want to do something about this rule. When doing permanent redirects, ALWAYS make sure that all your internal links points to the new URL, rather than towards the old URL, letting the browser do the redirect. Implementing this anti-pattern will absolutely slow down your site!

This week I have chosen to combine rule numbers 6 and 7. Why? Because they focus on pretty much the same thing: where to put style sheet and script references. According to rule number 6, you should put all your styling in the head section of your HTML document. The YSlow documentation explains why. There’s no magical formula you should know in order to obey this rule, so just do it.

The difficult thing about the two rules is putting JavaScript at the bottom. And by bottom I do not mean the bottom of the head section, but just before the closing body tag. In order to do this, first you need to write your JavaScript unobtrusive, which simply means that you separate your view (HTML) from your controller (JavaScript). When split into these two logical components, you won’t have any nasty document.write statements inlined in your HTML. Placing the script references should now be simple, but you typically still need to execute some JavaScript. Don’t worry, jQuery comes to your rescue with the ready function:


$(document).ready(function() {

// Place some code here

});

The function specified inside the ready method is executed after the DOM has been loaded.

When doing ASP.NET MVC, you most often use a master page for all the common stuff like your menu, header, footer, etc. I’ve used content place holders to ease the implementation of JavaScript in my views, with a master page, which looks like this:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<html>
<head>
<!-- Styles and stuff -->
</head>
<body>
  <!-- Your HTML goes here -->
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>

  <script type="text/javascript">
    $(document).ready(function() {
      <asp:ContentPlaceHolder ID="domready" runat="server"></asp:ContentPlaceHolder>
    });
  </script>
</body>
</html>

In your view, you will be able to add a content place holder and write JavaScript right inside. The code will run when the DOM is ready.

(Proofread by inWrite)

We all know it: zipping is a great way to compress the size of a file. This rule also applies on the web. Zipping responses from a server is natively implemented in the HTTP version 1.1 standard, which is why you don’t have any excuse left not to zip all your responses. I won’t go into a lot of detail on how zipping over HTTP works, but here is a short brushup.

When doing a request on a web server, the client can set the Accept-Encoding request header. If set to one of the valid values like “gzip,” the client tells the server that it is capable of handling a zipped response. If the server chooses to zip the response, it must set the Content-Encoding response header to a valid value like “gzip” or “deflate.” The browser checks for this header and unzips the response if necessary. This sounds a bit technical, but actually all of the above are handled by the browser. This means that all you have to do is tell your server to gzip encode your content. Pretty neat, right?

There are different ways to gzip encode web server responses. I typically use ASP.NET MVC for my projects, which does not have anything build in. I’ve seen different implementations in HTTP handlers and modules as well as custom action filters. I typically use WebOptimizer.NET by a fellow Danish developer, Mads Kristensen. It has a pretty simple HTTP module, which produces standard gzip/deflate by adding the WebOptimizer dll to your dependencies and pasting the following XML to your web.config:

<system.webServer>
  <modules>
    ...
    <add name="CompressionModule" type="WebOptimizer.Modules.CompressionModule, WebOptimizer"/>
    ...
  </modules>
</system.webServer>

It doesn’t get any simpler than this! The downside is that WebOptimizer doesn’t really evolve (last commit in 2009). If you have any proposals for a better and more recent implementation, please provide me with a link.

If you have access to configure the IIS, compression is natively supported. Scott Hanselman just wrote a great blog post on the subject.

(Proofread by inWrite)

We have reached rule number 4 in our journey into the exciting world of the YSlow rule set. Rule number 4 is all about caching. We have tackled the caching area a bit in some of the previous posts, but in this post I will dig more into this important area.

Showing webpages is all about getting resources like HTML, JavaScript, and images from the server and combining them in a showable way in the browser. I’ve previously talked about how to minimize the number of requests to the server, but what do we do when we have removed all the unnecessary requests with SquishIt and similar tools? One of the answers is caching, which is applicable for pretty much all pieces of a webpage. I will not explain any basics about HTTP caching. If you are not familiar with the subject, you should check out Mark Nottingham’s great Caching Tutorial.

So what’s the buzz about the Expires and Cache-Control headers? Both terms are part of the response header, which is used to tell clients if the response can be cached. Rather than explaining you all the theories, I would rather show you how I’ve implemented caching in one of my Danish ASP.NET MVC-based websites named myrating.

The problem

On my “product” pages I show similar items in a column to the right of the product info. Similar content is pretty performance heavy to calculate because of the algorithm, which is based on tags, ratings, and even more stuff. As a result, loading the product page was very slow, caused by the small similar items box.

The solution

I decided to do two things. The first solution was to wait for the rest of the page to show and load the info box async. I will show you how to do this in an upcoming post, but right now we will focus on the second solution: caching the response. I could have implemented the caching in an HTTP module but decided to implement a new action filter for ASP.NET MVC. This way I can annotate all the methods in my ASP.NET MVC project, the result of which can be cached. The action filter looks like this:


public class CacheableAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.Now.AddDays(7));
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.Public);
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(true);
    }
}

In line 5 I set the Expires header to a week from now. I’ve hardcoded this time span but could as well have implemented a property for making this configurable.

In line 6 I set the cacheability to public. This basically means that all parties can cache this, including both browsers and proxies.

In line 7 I set valid until expires to true to avoid cache invalidation sent from the browser. This way I control how long the response is cached, and not the browser.

Making responses cacheable for one week is now piece of cake. All I need to do is to add the Cacheable attribute to the action methods which can be cached like this:


[Cacheable]
public ActionResult FindSimilarItems(Guid id)
{
    ...
}

(Proofread by inWrite)

Hi and welcome to my new blog. During my years as a professional software developer, I’ve learned a thing or two about performance-optimizing software applications (both desktop and web applications). I’ve studied a lot of blog posts in order to solve different performance-related problems. This blog is my small donation back to the community.

I will primarily be writing about performance-optimizing websites in ASP.NET (MVC), but a lot of the concepts are portable to other technologies like PHP and Java Servlets (and even Ruby on Rails).

(Proofread by inWrite)