Skip to main content

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

Roland Barcia, Senior Technical Staff Member, IBM
Photo: Roland Barcia
Roland Barcia is a Senior Technical Staff Member and lead Web 2.0 Architect for IBM Software Services for WebSphere. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration and Persistence within the Enterprise: A Guide to Persistence Technologies.

Summary:  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.

View more content in this series

Date:  27 Feb 2008
Level:  Introductory
Activity:  494 views

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

About the author

Photo: Roland Barcia

Roland Barcia is a Senior Technical Staff Member and lead Web 2.0 Architect for IBM Software Services for WebSphere. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration and Persistence within the Enterprise: A Guide to Persistence Technologies.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

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
author1-email=barcia@us.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers