31 December 2007
Post Onload Download for better user loadtime
Weee, well this is a fun one. It's a method for ensuring that your users get the best response time possible, particularly on their first time to your page (Which in most cases, is most of your traffic). It will increase your bandwith usage, but overall, should lead to a better first impression to users.
The user will be given an embedded copy of JS/CSS files in the html page when they first come to your page. After the page loads, in the background, the cachable JS/CSS files will be loaded, and on subsequent pageloads (and in the future) cached versions will be used.
Follow along as we walk through a full example...
Yahoo notes that :
"For front pages that are typically the first of many page views, there are techniques that leverage the reduction of HTTP requests that inlining provides, as well as the caching benefits achieved through using external files. One such technique is to inline JavaScript and CSS in the front page, but dynamically download the external files after the page has finished loading. Subsequent pages would reference the external files that should already be in the browser's cache."
This brings up an interesting idea, that if a user has arrived without a cached version of the file in their cache, that we can inline the stylesheets and JS into one HTML document to reduce HTTP GETs. Additionally, after the page is loaded, instruct the browser to then get the inlined files and cache them at that point. The GETs get delayed until after the page is loaded, so it does not remove the need for them (it also increases bandwidth on your part as the user gets them embedded in the page, and then gets them again to cache them for further page loads). However, this can increase the page load time.
Yahoo's mentioned strategy works well for them, as I would bet most of their traffic arrives via a main landing page, but what about all other pages? Most of my traffic arrives via search results referrals. Can we still make this work?
So, how would you go about doing this?
How do we know if the user has the object in their cache? Well, the easiest way would be to set a cookie when the user has downloaded the information, and setting a lifetime equal to that of the expiration of the data. True, if a user clears his cache or his cookies, then there will be a mismatch, but in both cases, the user will not be left in the dark.
If the user clears his cookies, but has files in cache, then he will get the inlined files, and the post onload download will just result in not redownloading them as they will be cached already. If the user clears his browser cache, but not cookies, then the page will just reference the CSS/JS externally and the user will download them fresh without the benefit of caching.
Let's run through it in PHP, and note that it can be adapted to other languages.
We will create a method to check for a cookie and either embed the CSS/JS or put the external files.
-
function embedStyle($cookie,$jsFiles,$cssFiles) {
-
if($cookie) {
-
foreach($jsFiles as $jsFile) {
-
echo '<script src="http://www.artofscaling.com/article/wp-admin/%5C%27;%0A%20%20%20%20%20%20echo%20;%0A%20%20%20%20%20%20echo%20%5C%27" type="text/javascript"></script>';
-
}
-
foreach($cssFiles as $cssFile) {
-
echo '
-
<link href="http://www.artofscaling.com/article/wp-admin/%27;%3Cbr%3E%3C/link%3E%0A%20%20%20%20%20%20echo%20$cssFile;%3Cbr%20/%3E%0A%20%20%20%20%20%20echo%20%27" rel="stylesheet" type="text/css" />';
-
}
-
} else {
-
//embed the actual files into the document
-
//and add post onload download script
-
echo '<script language="JavaScript"><!-- window.onload=function(){ var req;\\';
-
-
foreach( as ) { echo \\'if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else { req = new ActiveXObject("Microsoft.XMLHTTP"); }\\'; echo \\'req.open("GET", "\\'..\\'", true);\\'; echo \\'req.send(null);\\'; } foreach( as ) { echo \\'if (window.XMLHttpRequest) { req = new XMLHttpRequest(); } else { req = new ActiveXObject("Microsoft.XMLHTTP"); }\\'; echo \\'req.open("GET", "\\'..\\'", true);\\'; echo \\'req.send(null);\\'; }
-
-
echo \\' document.cookie = "userCached=true"; } //--></script>';
-
}
-
}
To call it, just add
to your header.
As you can see, this can do most of the heavy lifting for you. There are some downsides to this of course. If you cache static versions of your pages (like WP-super-cache for example), then this method will not work without modification.

