How fast a web page can be displayed is still an important issue. Nowadays, it's not as much how quick the page is rendered at the server that should be the key focus, rather the user experienced load time at the client. Web pages tend to get more and more scripts to handle things like nicer interactions and smoother communication (like Ajax). This tends to prolong the load time since the scripts are loaded synchronously, one round trip to the server for each file to include. The same goes for stylesheets.
Enter the Solution
Wouldn't it be great if it was possible to keep the scripts and stylesheets as separate files, in human readable format, but at the same time send a minified all-in-one file to the web browser? Maybe even gzip-compressed to optimize the transport even further? Well, that's what we'll do here in this article!
Let's start by setting some design goals for our new component that will deliver this magic:
This code should ...
- .. be built as a
- .. usage shouldn't be harder than current
- .. produce a single, minified versions of the scripts/stylesheets.
- .. deliver this file gzip:ed if requesting web browser is compatible.
- .. have an easy way to disable it to ease script debugging.
- .. only recompact the files if any of them has been changed (use smart caching at the server).
- .. cache the files at the client, but in a manner that will reload any changed file.
- .. NOT reinvent the wheel. Reuse proven code to minify both scripts and styles.
As there are a few really good minifiers/compressors out there, I decided to use one of them instead of writing my own. The choice fell on Yahoo! UI Library: YUI Compressor for .NET (under Ms-PL licence) since it's well proven to work and does a really good job. If you however feel like using some other code for compressing the scripts/CSS, you will be able to easily change the implementation in the classes
Using the Code
I won't go into too much detail of the actual implementation, since I've tried to comment as much of the code itself as possible. But I will give you a little starting point by describing the different classes in this project.
|Common.cs||Collects useable functions that are called from other parts of the project.|
|Config.cs||Includes all properties read from the web.config file.|
|CssMinifier.cs||Code to handle the compression and minification of the stylesheets.|
|GetPackedFile.cs||Page codebehind which will be used to get the right file on request from client.|
WebControl to use on your pages in order to collect the stylesheets that should be packed together.
Using SmartInclude in your Project
I assume you have a working assembly, either from the demo project or one which you've built yourself.
Let's start by adding
SmartInclude to your project in the following steps:
- Open your project.
- Add a reference to the
SmartInclude assembly (or project if you intend to do some debugging) for your web project.
- Open your web.config file and add the following lines in your
<add key="SmartIncludeDebugMode" value="false" />
<add key="SmartIncludeXhtmlMode" value="false" />
<add key="SmartIncludePath" value="/includes/" />
Change the values to match your project. The values are:
|Set the value to |
true in order to enable debugging. In debug mode, the included files are loaded in the original, uncompressed/non-minified version as they appear on the server.
Should be set to false unless you actually are debugging the code as this will override any speed ups!
|Set this to |
true if you are using XHTML so that
SmartInclude will render the HTML tags correctly.
|Set this to the absolute path where you want to store the compressed files and load them from.|
- Copy Get.aspx from the
SmartInclude project into the same path you wrote in SmartIncludePath (in the previous step).
Do the following steps for all pages you want to speed up:
- Open the aspx file for the page you wish to speed up by using the
SmartInclude web control.
- Add a line in the top (as the second line) to register the
SmartInclude web control on your page:
<%@ Register TagPrefix="smart" Namespace="Kaliko.SmartInclude"
<smart:IncludeScript Url="/myScript.js" runat="server" />
- For all CSS includes, change:
<smart:IncludeCss Url="/style.css" runat="server" />
That's it! You've just speeded up the user perceived page load times in your web project.
Points of Interest
There are plenty of useful tools around to help you to speed up the page loading. Two of these are YSlow from Yahoo and Page Speed from Google, both available as plugins for Firefox (with the Firebug plugin installed). I suggest you try these plugins for further suggestions of optimization points (now when your script and stylesheet includes should get a grade A ;)).
There's also one known limitation in the code. It doesn't handle different media targets for stylesheets. For instance, if you have a different stylesheet for printing, it should still be included by the
- 1.2.0 - Latest sources with a few fixes applied
- 1.0 - Public release
- 0.9 - Proof of concept