Archive for the ‘progressive enhancement’ Category

Letting Google Help With Your Site Performance

Let’s face it, cross-browser JavaScript and AJAX without a helper library or framework is pretty difficult. However, these libraries can be pretty hefty when it comes to page download size, especially if sent uncompressed and un-optimized. Most of the libraries have a statement in their docs that says something along the lines of “grow up and compress your JavaScript” but not all of us have sufficient access to their web host to actually be able to do that. Enter Google. Google’s AJAX Libraries API serves as a content distribution network for providing pre-compressed versions of the web’s favorite Web 2.0 JavaScript libraries:

Access to these libraries is quite simple, in fact loading prototype can be accomplished with the following four lines of code:

<script src="http://www.google.com/jsapi"></script>
<script>
	google.load("prototype", "1.6.0.2");
</script>

Pretty simple, but let’s look at some metrics.

With Google Without Google
(no cache) (local cache) (no cache) (local cache)
KB Time KB Time KB Time KB Time
66 982ms 4 980ms 252 2.14s 0 1.19s

As you can see, the Google version is significantly faster and smaller on the initial load, subsequent loads a little less obvious, but still slightly faster. However, this test was not all that scientific, since I really only have the ability to do this with Firefox and Firebug, I only did it once, and my network speed can vary significantly from request to request. Despite all of that, testing this across a few other browser/OS combinations does reveal a pattern where the Google AJAX Library API pages do feel faster, even if only by a fraction of a second. I’ve provided my test pages, with Google and without-Google, for you to perform your own tests, and I’d love to hear what other people think and see their results.

The verdict, I like it, but I have a few caveats. First, as pointed out to me by the Unscrutable Designer, you’re relying on a third party site to host your scripts, in this case it means you need to trust Google to not be evil. Personally, I do, but that is a decision to be made on a case-by-case basis. Secondly, you have to trust the reliability of your content distribution network, can you risk your JavaScript functionality if Google’s server goes down? Thanks to progressive enhancement, having no library should be basically the same as no JavaScript, so my properly implemented site should still function, so this is personally not a show-stopper for me.

Now, one last thought. Keep in mind that this is not the most optimal solution since it still makes a request for each library you load and the libraries themselves are not optimized, but it does bring along with it an interesting benefit. The more sites that use this service the higher the chance of getting a local cache hit on one of these files, which of course means one less download.

Progressive Enhancement and LightWindow

Nothing says Web 2.0 like a lightbox, those nifty, little, modal dialogs that let you create pop-up-like functionality without the worry of pop-up blockers. There are quite a few variations of this concept, including Lightbox JS (and its many variants including Lightbox Gone Wild by the makers of Wufoo), Slimbox, and my personal favorite LightWindow. In general, they’re all pretty unobtrusive, but in this little tutorial I’m going to kick up the progressive enhancement a notch and make LightWindow even better!

Let’s start with a client who wants to use a lightbox to display a multi-view image viewer for an e-commerce site. In true progressive enhancement fashion, if JavaScript is disabled, the user should still be able to perform the basic functionality of the site. So, let’s assume our site has a simple layout with a header, a footer, and a main content area that looks something like this. When JavaScript is disabled the image viewer should show up with the header and footer, when it’s enabled, it should show up in a lightbox without the header and footer. So how do we do it?

LightWindow can be used to display any given webpage by simply setting the class of a link to that webpage to lightwindow. Simple enough. When the lightwindow.js file loads it searches your document for anchor elements with a class of lightwindow and adds the necessary onclick handler to make the link open in a lightbox instead of as a normal page, as unobtrusive as it gets. However, since we want our result page to look differently depending on whether it’s being displayed as a lightwindow or a regular page, we need some way to tell our back-end the display form-factor. To accomplish that we’ll add my own little progressive enhancement to the page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Event.observe( window, "load",
	function(e) {
		$$('.lightwindow').each( 
			function( elem ) {
				if( elem.href ) {
					if( elem.href.indexOf('?') == -1 ) {
						elem.href += '?';
					}
					elem.href += "lightwindow=true";
				}
			}
		);
	}
);

This is simple enough prototype.js JavaScript code that crawls the DOM for elements with a class set to lightwindow and adds a parameter of lightwindow=true to the href attribute. With this parameter in place, the back-end now knows which form-factor to use when rendering the page and we can accomplish our goal with some simple PHP code. (Pardon my PHP, I’m by no means a PHP expert, this is only meant to be a simple example.):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php if( $_GET['lightwindow'] != 'true' ) { ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" debug="true">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-16" />
	<title>Example Lighwindow (JavaScript Disabled)</title>
	<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
</head>
<body>
<?php } ?>
	<div class="container" <?php if( $_GET['lightwindow'] == 'true' ) { echo "style=\"width: 300px;\""; } ?>>
		<?php if( $_GET['lightwindow'] != 'true' ) { ?><h1 id="header">Header</h1><?php } ?>
		<p>
			This is my lightbox content, if JavaScript is enabled on your browser you should be seeing it in a LightWindow, 
			if it's not, you should see it with a header and footer similar to <a href="index.html">this page</a>.
		</p>
		<?php if( $_GET['lightwindow'] != 'true' ) { ?>
		<ul id="footer">
			<li><a href="/">Back to EricDeLabar.com</a></li>
		</ul>
		<?php } ?>
	</div>
<?php if( $_GET['lightwindow'] != 'true' ) { ?>
</body>
</html>
<?php } ?>

Problem solved, have a look here and click on the “this link” link. Of course there are a few more programming alternative along these lines, including modifying the LightWindow object at runtime to prevent a second crawl of the DOM for elements with the lightwindow class, theoretically improving performance, but I’m going to leave that for another article.

As an interesting side benefit to this technique, web crawlers like the Googlebot, which don’t interpret JavaScript, will follow the link to the lightbox page and receive a full page as opposed to just the page content. This Allows the robot to continue crawling your site through the navigation and also allows it to see your page title and meta tags. Now, just a little forewarning, be careful with this technique, if you abuse it, it may be considered cloaking any you could have your site delisted for violating the webmaster guidelines. So in other words, use this technique to provide context and don’t try and stuff the pages with keywords or do anything underhanded.