Improving front-end website performance in ASP.NET MVC

Load times, according to people like google, are important.  I kinda see it as basic politeness; wasting a user’s (or worse, a customer’s) time making him wait for my site to become active is a bit rude.  According to YSlow! (a Firebug plugin within Firefox), one should:

  • Reduce the number of external requests (or; make one big Javascript/CSS request instead of many little ones) – browsers typically will only hold two open connections per domain, and scripts load sequentially (I gather because of the possibility of document.write calls modifying the DOM, which would be a shared resource if they were allowed to load and execute in parallel).
  • Reduce the size of external requests (less on-the-wire weight is better; remove comments and white-space).
  • Compress external requests where possible (gzip/deflate compression will trade CPU cycles per request to gain better on-the-wire weight).
  • Use a far-future cache-header for assets that won’t change often (so that clients don’t need to receive a new copy on each visit).
  • Move scripts to the end of the document so the content loads first – the user has stuff to look at while scripts arrive.

Happily, all achievable with only a modicum of effort.  Yahoo has released its YUICompressor component to open-source, and there’s a .NET version available from codeplex – this takes care of minifying Javascript and CSS.  So, all we need to do is glue the files together and push that glob to the compressor.  Right?  Well, we also have to tell our component which things to work on.  This set will vary, usually, per page (ideally, we will offload all script/style to separately-loaded assets, since we can cache those and slim down our actual document at the same time by doing so).  It’s more pleasant to develop within individual files; one file per class/feature/whatever; given that we’re not perfect, it would also be invaluable to be able to turn on a debug-mode so we can debug through readable code.  

Lastly, do this stuff at run-time, because maintaining config or build-automation to do it would save some CPU cycles at the expense of developer time (can you spot someone that’s been burned by that kind of thing…? :-P ).

I’m going to be doing this within the context of ASP.NET MVC (and maybe fiddle with Spark’s modularity feature once it’s done).  My list of features:

  • Register an include (from both the master-page and the views).
  • Write out the include-combination (or, in debug mode, write out each include separately, raw and untouched).
  • Combine the includes within the set that is registered (glue the files together – and, necessarily, read the files from where-ever they live!).
  • Make it possible to link to the combination (a controller with actions to respond with the combination when tickled via an appropriate GET)
  • Minify the combination.
  • Compress the combination (gzip/deflate – and detect which browsers we shouldn’t do this for – I’m looking at you, IE<=6, you lying so-and-so…).
  • Cache the combination with a far-future expiry (and therefore also use a URL amenable to browsers caching it).
  • Generate an ETag.
  • Support a debug-mode where the includes are written out one-by-one and raw.
  • Be trivial to understand and add to your own application :-)

I’ll host the source in github, and blog as I go.

Some more references for front-end performance:

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • DotNetKicks
  • DZone
  • LinkedIn
  • Technorati

4 Comments

ErikJuly 27th, 2009 at 8:35 am

This is very interesting…

Looks like the kind of feature that the ReadZ.AssetManagement library could use (see http://weblogs.asp.net/rashid/archive/2009/05/02/script-and-css-management-in-asp-net-mvc-part-2.aspx).

Forking for sure :D

Erik

[...] the last few days, I’ve forked MvcContrib on github and merged in my IncludeCombiner library to it as MvcContrib.IncludeHandling.  It was accepted (thanks Jeremy!), and is now part of [...]

ASP.NET MVC Archived Buzz, Page 1October 28th, 2009 at 12:30 pm

[...] to Vote[Del.icio.us] Improving front-end website performance in ASP.NET MVC | Never Run With Scissors (10/2…Wednesday, October 28, 2009 from t1mmyb"Load times, according to people like google, are [...]

Shannon DeminickAugust 25th, 2010 at 4:04 pm

Please have a look at ClientDependency (http://clientdependency.codeplex.com)

this pretty much does everything in regards to registering scripts/styles, compressing, combining, detecting ‘rogue’ scripts styles that aren’t explicitly registered, etc…, etc… There’s a huge features list on the CodePlex site.

works with MVC and is part of the core of Umbraco now too.

Leave a comment

Your comment