A common issue encountered when developing web applications with the Dojo Toolkit is a startup lag caused by the dynamic loading of modules and resources, further aggravated by a flash of unstyled content before the template system kicks in and sets up your widgets. This is especially true when using numerous Dijit components, and even more apparent when not using a custom build (such as loading your files from the Google or the AOL CDN). While it is typically recommended to use a custom build, it isn’t always practical, or even necessary. Perceived speed is speed, and we should do something about it.

Dojo is a very flexible toolkit, and can bend and otherwise be manipulated to handle any use case. Personally, I am a fan of the progressive use case: where JavaScript is used to enhance an otherwise perfectly working collection of clean markup and good styles. Sometimes though, especially in the case of intranet applications or “admin panel” type web interfaces, you will find yourself using many layout widgets and form components. Delivering content quickly in this case is essential, and hiding any ugliness resulting from template substitution is a vital aspect to delivering the best possible user experience. Today, I’m going to go over a common technique to provide at least the perception of perfectly designed full-page layout applications.

We’ll start with a sample application, loading Dojo and several Dijit components from the AOL CDN tree:




	

	 
	
	

	
	
	



	

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus, mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. Nam tempus ornare lorem. Nullam feugiat.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus, mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. Nam tempus ornare lorem. Nullam feugiat.

You can see this example in action now.

The total size of CSS, JavaScript and HTML is 645KB, spread across 91 requests, taking a total of 2.13 seconds to load and parse when loaded from the local file system. This is less than ideal, and we’ve not even started added complex content! (To be fair, this code includes all comments inline, and no effort has been made yet to optimize this code.) You can see the various lorem paragraphs jump into place, much to the dismay of your designers and users alike. The build system will reduce this impact significantly, but we’re still just developing here, and keeping all the code modular is in our best interest.

Updating all Dojo URLs to point to the AOL CDN, we are able to reduce the page overhead to 104KB, taking a total of 2.12 seconds. In the next article we’ll convert this to a local tree again, and illustrate how a custom build can optimize this even further.

You’ll notice we’re calling dojo.parser.parse() from within a dojo.addOnLoad() function. Had we set djConfig.parseOnLoad = true, any registered addOnLoad functions wouldn’t execute until after parsing takes place. In most cases, this is convenient. In this case, however, we want more granular control over page-load behavior.

The technique we’ll be using to hide the rendering process is simple, and mostly uses plain CSS selectors and design, and minimal amounts of JavaScript to achieve the desired results. We start by adding a new node with position:absolute, taking it out of the layout flow, giving it a high z-index, and a centered background-image of a spinning loader. We’ll then overlay this node across the entire viewport, and do all of our parsing in the background. Add a DIV element with an id of “preloader” in the page (as close to the top of the markup as possible is best, but will work anywhere), and some simple rules:


If all you see is a spinning icon, we’ve succeeded. Granted, we can’t interact with our page at all now, but we didn’t see any unstyled content. The next step would obviously be to show the content immediately after dojo.parser has run. This is where it is important to have onLoad parsing turned off (via djConfig.parseOnLoad = false) because, as mentioned earlier, addOnLoad fires after parsing when set to true.

Let’s create a simple function to call immediately after parsing to hide the overlay. It can be as simple as setting the CSS property “display” to “none”:

	var hideLoader = function(){
		dojo.style("preloader", "display", "none");
	}
	dojo.addOnLoad(function(){
		dojo.parser.parse();
		hideLoader();
	});

A preview of this step: Simply hiding the overly when ready.

It can also be something more aesthetically pleasing, like a fadeOut call. Fading out a node doesn’t affect the ‘display’ property at all, which we’ll need to set to ‘none’ to allow clicks and interaction, as the overlay is actually still in place, just hidden. We can replace our hideLoader function with a simple animation:

	var hideLoader = function(){
		dojo.fadeOut({
			node:"preloader",
			onEnd: function(){
				dojo.style("preloader", "display", "none");
			}
		}).play();
	}

The next optimization we can do involves a small code change. If no dojo.require() calls are made before the DOM is ready, addOnLoad will fire immediately. This works to our advantage here: by loading the simple 26KB dojo.js only, we’re given a really strong set of APIs, without ever including any Dijit components. Let’s defer the loading of the Dijit files until after the DOM is done (ensuring our overlay is up and spinning before ANY XHRs take place). Simply wrap them in an addOnLoad function, still defining our hideLoader function, though this time calling it from within an embedded onLoad function:

	

The end result of our trivial code change can be seen in the after onLoad example.

dojo.addOnLoad is smarter (or at the very least does more) than body.onLoad / document.ready / et al. It knows when Dojo modules are in flight or otherwise being requested, and re-fires after all dependencies have been solved. You can use this technique over and over as often as you like. If a module is already ready, dojo.require() is a no-op, and any subsequent dojo.addOnLoad calls will fire relatively quickly.

That’s all there is to it! We’re still using 92 requests (43 from the CDN), and the same byte count on code, and we’ve even actually slowed down the page loading by 700ms (the duration of the fadeOut animation) but perceived speed is speed, and this simply feels a lot faster. Once we’re done developing this page, we can move on into creating a build to limiting the number of requests and concatenate all the CSS together in one fell swoop. The key here is giving the user the sensation of “working”. The loading indicator screams “bear with me, I’ve not left you hanging.”

A designer with good CSS skills can certainly style the content within the preloader node using any standard techniques, customizing the feel with ease, or a developer can create a more riveting animation to hide it. Anything is possible in with the new 1.2 release of the Dojo Toolkit. The Base 26KB dojo.js provides all the utilities needed for Animation, Events, Ajax, Package Loading, Styling, and Node Manipulation, Object orientation, JavaScript lang utilities and the Dijit add-ons can be deferred until much later in a page life cycle to accelerate page load time and application responsiveness.