Comment lines: Roland Barcia: Improve initial download time of your Dojo applications

Once an Ajax application is loaded, it subsequently fetches smaller fragments of data and content to avoid the overhead of re-rendering the entire page, thus improving performance. The tradeoff that enables this to happen is that the initial download of your application will usually take longer. This article looks at ways you can reduce the initial download time of your Dojo applications and still get great performance. This content is part of the IBM WebSphere Developer Technical Journal.

Share:

Take only what you need

Asynchronous JavaScript and XML (Ajax) applications can improve the performance of some Web applications. Once the application is loaded, fetching smaller fragments of data and content can help avoid the overhead of re-rendering the entire page. The tradeoff, however, is that the initial download of your application will usually take longer.

I have been working with Dojo applications for a few years now. Both the IBM® WebSphere® Application Server Feature Pack for Web 2.0 and Project Zero now include an IBM distribution of the Dojo Toolkit with some value add extensions. Due to the modular nature of the Dojo Toolkit, the initial load can take a considerable amount of time because each module that you use might require a few JavaScript™, HTML, and CSS files to be downloaded. This creates a lot of additional IO over the network beyond just the size of each module.

In general, this modularity is necessary for programmers because it enables easy debugging and coding, but once the application is written, this modularity is not essential -- or needed. There are several ways you can reduce the initial download time of your Dojo applications.


Using the Dojo build and package system

The Dojo Toolkit has a packing and compression technology that packs the Dojo code you use in your applications into a single file, and then compresses it to minimum size, using compression technology called Dojo ShrinkSafe. Most Dojo applications should use this technology as part of their deployment, as it will greatly increase the application’s performance, specifically the initial download. You simply create a profile for your application in which you specify which Dojo components you are using. Listing 1 shows an example.

Listing 1. Sample profile
dependencies ={

    layers:  [
        {
        name: "example.js",
        dependencies: [
			
			"dojo.*",
			"dojo.parser",
			"dijit.dijit",
			"dijit.Declaration",
			"dijit.layout.LayoutContainer",
			"dojox.layout.ContentPane",
			"dijit.Toolbar",
			"dijit.layout.AccordionContainer",
			"my.widget.Super"         
       	]
        }
    ],
	
	
    prefixes: [
        
		[ "dijit", "../dijit" ],
		[ "my", "/myWidgets"],
		[ "dojox", "../dojox" ]
    ]

};

You would then run a command line build tool, passing in the profile with various options. The Dojo build can then place all the code needed by your application (including JavaScript, HTML, and CSS) into a single file and compress it. Using this method, I have seen the number of IO calls in the initial download size of an application be reduced from over 200 calls down to just two or three. I have also seen the overall size be reduced by about 60%. A developerWorks tutorial on using the Dojo build and package system will be available soon, but in the meantime, more information on the package system and custom builds is available on the Dojo Web site.


Lazy load and cache your Dojo content

Another practice that can greatly increase initial download size is lazy loading the content portion of the page and caching it once it is downloaded. Rather than load everything you need when the application is first accessed, it is sometimes better instead to load only some portions of the application at that time. It is very possible that a user could visit your site and never touch certain parts of your Web application, so any time spent downloading those consequently untouched sections is wasted. Therefore, you don't need to download portions of your application that might not be used. Furthermore, first impressions say a thousand words: if you do not show your initial homepage quickly, it can turn users away even quicker.

In general, you want to load the layout with some initial menus and fetch the home content after loading. A common Dojo application is typically made up of some layout elements. Consider Listing 2:

Listing 2. Layout
<body class="tundra">
	<div dojoType="dijit.layout.LayoutContainer" 
		layoutChildPriority="top-bottom" 
		id="main" 
		class="layout" >
		<div dojoType="dijit.layout.ContentPane" 
			layoutAlign="top" class="banner">
			<h2>Electronic and Movie Depot !!</h2>
		</div>
		<div dojoType="dijit.layout.ContentPane" 
			layoutAlign="top" class="menu">
			<div dojoType="dijit.Toolbar" id="mainMenuBar">
				<div dojoType="dijit.form.Button" 
					id="productListMenu" 
					onclick="showItem('productList',
						'product/product.html');">
					Shopping
				</div>
				<div dojoType="dijit.form.Button" 
					id="orderListMenu" onclick="showItem('orderPage',
						'cart/cart.html');">
					Shopping Cart
				</div>
			</div>
		</div>
		<div dojoType="dijit.layout.ContentPane" 
			class="mainArea" 
			id="center" layoutAlign="client">
			<div dojoType="dojox.layout.ContentPane" 
				executeScripts="true" id="productList" 
				style="display:none">
			</div>
			<div dojoType="dojox.layout.ContentPane" 
				executeScripts="true" 
				id="orderPage" 
				style="display:none">
			</div>
		</div>
	</div>
</body>

Listing 2 shows a couple things. I created a simple method to load an HTML fragment into a particular content. I also utilize the dojox.layout.ContentPane instead of the default dijit one. The extended content pane enables the execution of JavaScript when the region is loaded. This way, not only can I lazy load the HTML content, I can also load the associated logic lazily. Listing 3 shows the implementation of the utility methods I wrote.

Listing 3. Lazy loading
var loaded = new dojox.collections.Dictionary();

function hideAll()
{
	console.debug("Hiding other content");
	var ids = loaded.getKeyList();
	console.debug("Getting ID -> " + ids);
	console.debug("List is Array");
	for (var id in ids) {
		console.debug("Getting section -> " + ids[id]);
		var section = dijit.byId(ids[id]);
		console.debug("Got Section -> " + section);
		if (section) {
			console.debug("setting DOM");
			section.domNode.style.display = "none";
		}
	}
	console.debug("Content is hid");
}

function showItem(key,template)
{
	hideAll();
	console.debug("Show Item -> " + key);
	var item = dijit.byId(key);	
	console.debug(item);
	if (item) 
	{
		if(!loaded.contains(key))
		{
			item.setHref(template);
			item.refresh();
			loaded.add(key,template);
		}
		
		item.domNode.style.display ="block";
	}
}

/**
 * Load Default page
 */
dojo.addOnLoad(function loadDefault()
{
	console.debug("Loading initial state");
	showItem('productList','product/product.html');
});

When showItem is called in Listing 3, I hide any content that might be visible in the main body. I then check to see if the HTML has been loaded. If not, I download the template and then cache it inside a Dojo dictionary. The next time I ask for this page, it will just show the region. I also load a default page using the dojo.addOnLoad method.

When showItem is called in Listing 3, I hide any content that might be visible in the main body. I then check to see if the HTML has been loaded. If not, I download the template and then cache it inside a Dojo dictionary. The next time I ask for this page, it will just show the region. I also load a default page using the dojo.addOnLoad method.


Don't make everything a dijit

It is quite tempting to create dijits (Dojo widgets) out of major application components. For example, in Listing 4, you see an example of an application made Dojo dijits.

Listing 4. Application components as dijits can decrease download time
<div dojoAttachPoint = "registerId"
	dojoType="registration:RegistrationWidget" 
	style="display:none"
>
</div>
<div dojoAttachPoint = "datacenterId"
	dojoType="datacenters:DataCentersWidget"  
	inputTopic="no.show.datacenter" 
	style="display:none">
</div>

In Listing 4, I wrapped each application component in a dijit. In turn, every dijit was composed of sub-dijits. You can even conceive of loading the whole application as a super dijit:

<div id = "layout" dojoType="layout:EEFLayoutWidget" class="layoutDef"></div>

The problem is that you negate (or make it extremely complicated to) lazy load content, especially if you include all your widgets as part of a build. I have found that it is best to create dijits for UI components (Data Grid, specialized ComboBox, special text area) and than load plain HTML templates that use the dijits.

By following some good guidelines and practices, you can easily reduce the amount of time it takes to download your application and still benefit from some of the performance advantages that Dojo has to offer.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Web development
ArticleID=291159
ArticleTitle=Comment lines: Roland Barcia: Improve initial download time of your Dojo applications
publish-date=02272008