Create optimized Dojo builds for your custom Dojo artifacts

Create a custom Dojo build for your custom widgets without including any modules from the dojo/dojox/dijit packages into your build output. Custom Dojo builds reduce the number of modules to be downloaded by combining all the modules into a single file, thereby reducing the number of network calls required for the individual module files. These techniques were developed with a real-world project where compact packages were a requirement. This article helps you to create optimized Dojo builds using the Dojo build tool.

Share:

Manjunath Ganga (manganga@in.ibm.com), Software Engineer, IBM

Manjunath Ganga has been a software developer for the WebSphere Commerce IBM India team for the past 2 years. He is currently working on a social commerce solution for Websphere Commerce. His areas of expertise are Java, J2EE, Ajax, Dojo, and Wesbphere Smash.



10 November 2009

Also available in Japanese

Introduction

Dojo contains thousands of files in its source distribution, organized into packages. You can also create your own custom modules, preferably in a separate package away from the Dojo source tree. Each dojo.require() statement results in a synchronous HTTP call to the server for the requested module. Because browsers wait for each synchronous call to complete before continuing with anything else, this will significantly impact performance, especially so with larger applications that have many module dependencies. Also, the modules in their original form will require more time and bandwidth to download.

Custom Dojo builds help to improve performance by performing the following tasks:

  • Grouping individual modules into layers. A layer, which is one large .js file, loads faster than the individual .js modules that comprise it.
  • Internalizing external non-JavaScript files. For example, in the case of Dijit templates, it pulls the entire HTML template file and assigns it to a string.
  • Compressing the layer with the tool Shrinksafe. Because layer files can be large, this compression can reduce the file size substantially, which can result in a faster load time. And, as the file size is reduced, it takes the browser engine less time to parse.

Now, consider a situation where you have developed custom Dojo artifacts (for example, custom Dojo widgets) and hosted them at a site so that potential clients can deploy these artifacts to their site. Further, you have also created a layer file for the custom Dojo you have developed so the clients can now make a single request for the layer file as opposed to multiple stand-alone requests for each of the required modules.

Also, if the client site that deploys the custom Dojo artifacts is already Dojo enabled, you can further reduce the size of your custom layer file by not including any modules from the Dojo/Dijit/Dojox packages, as they would already be available at the client site. This article demonstrates the creation of one such custom layer file, which does not include modules from the Dojo tree.

Figure 1. Deployment scenario
Two boxes, with arrows between them showing the layer file going from client site and returning custom dojo layer file from your site to client site

Prerequisites

In this article, I demonstrate the creation of a Dojo layer file using the Dojo build tool. The prerequisites for the Dojo build tool are:

  • Java™ 1.4.2 or later (Java 1.5 recommended)
  • A source build of Dojo. (See Resources for download)

Setup

The setup involves the following steps:

  1. Create a directory, for example build, which will act as the root directory for all your work.
  2. Create a new directory under build, for example dojo1.3, and extract the Dojo source build to it. Throughout the rest of the article build/dojo1.3 will be referred to as dojoRootDir.
  3. Create a directory custom under dojoRootDir. This directory will house all the custom Dojo artifacts that you will develop.

Now you should have the application directory structure shown in Listing 1 under dojoRootDir.

Listing 1. Application directory structure
build/ 
                 dojo1.3/ 
                                  custom/ 
                                  dojo/ 
                                  dijit/ 
                                  dojox/ 
                                  util/

Dojo profiles

A Dojo profile controls how the build system creates the custom layers and is one of the mandatory input parameters for the Dojo build tool. This is a JavaScript file and functions similar to the build.xml file used for Apache Ant. The Dojo profile encapsulates all the necessary information required for the Dojo build tool to create the custom Dojo layers. This article shows how to create one such profile required to build the intended custom Dojo layer. A sample profile script is attached as part of this article (see Download).

Listing 2 shows the Dojo build profile structure.

Listing 2. Dojo build profile structure
dependencies = {
          
            layers : [ ],

            prefixes : [ ]
 
   };

The layers section is an array of layer files you want to create. (You can create more than one layer file per one execution of the build.)

The prefixes section is an array of individual prefix objects. Each prefix object describes where a particular top-level module's source is found relative to dojoRootDir/dojo.


Running the custom Dojo build

The Dojo build script is located in the dojoRootDir/util/buildscripts directory. From this location, you can run the build tool as follows:

  ./build.sh profileFile=<path to the profile file> 
            action=<actions>

where the options are as outlined in Table 1.

Table 1. Dojo build options
Build Option NameDescription
profileFile A file path to the profile file. This is used when the profile is outside of the dojoRootDir/util/buildscripts/profiles directory.
action The build actions to run. Can be a comma-separated list, like action=clean, release. The possible build actions are: clean, release. Default: "help".

Run build.sh without any options to see a list of all supported options. (Note: In Windows® use build.bat)


Creating your custom Dojo profile

You want to create a Dojo layer file that contains the resources located under the custom directory in Listing 1, but this layer file should not include any modules from the dojo/dojox/dijit packages (as these modules will be available at the client site).

The key to eliminating modules from a layer is to include these modules in a discard layer and specify this layer in the layerDependencies attribute of your target layer. The following example should help in explaining this further.

Say you are creating a layer file layerA, which should include module modA (which has dependencies for modules modB and modC), but layerA should not include modules modB and modC (maybe because these modules are included in a separate layer). This can be accomplished by including modules modB and modC in a layer discardLayer, which in turn should be specified as a layer dependency for layerA. Listing 3 shows how to create one such profile.

Listing 3. Sample Dojo profile illustrating how to create discard layers
dependencies: {

     layers: [
          {
          	"name": "discardLayer",
          	"discard" : "true",
          	"dependencies": 
               [
               	"custom.modB",
               	"custom.modC"
               ]
          },

          {
          	"name": "layerA",
          	"layerDependencies" : 
               [
               	"discardLayer"                             ],
          	"dependencies" :
               [
               	"custom.modA"
               ]
          }
            ],

     prefixes: 
     	[
          ["custom": "../custom"]
     	]

}

Note 1: The layerDependencies attribute specifies other layers that are prerequisites for a layer; resources in the prerequisite layers are not duplicated in the current layer being built. That is, if the Dojo builder locates a dojo.require statement in a source file, but that resource has already been placed in one of the dependency layers, then that resource will not be included in the current layer.

Note 2: The ordering of the layer files in the profile is important. The layer files will be created in the order they appear in the profile. This is important for you because the discard layer (discardLayer) should be defined before your layer file (layerA). This ensures that the modules included in the discard layer will not be included in your layer. The layers that have the discard attribute set to true will not be saved after the completion of the build. So the discardLayer will not be saved after the build completes; it just ensures that modules modB and modC are not included in layerA.

Using this approach, you can build your layer file using the following steps.

  1. Create a discard layer for the modules from the Dojo package.
  2. Create a discard layer for the modules from the Dijit package.
  3. Create a discard layer for the modules from the Dojox package.
  4. Create your layer by including modules that are required and specify the above layers as layer dependencies.

Create a profile as shown in Listing 4, and save it as myProf.profile.js.

Listing 4. Dojo profile to include your custom modules and eliminate modules from Dojo/dijit/dojox packages
dependencies = {
layers: 
[   
//This layer is used to discard modules             
//from the dojo package.      
                  
{ 		    
name: "dojo.js",
customBase: true,
discard: true,
			dependencies: 
[
                  	"dojo._base"
			]
			
		},
		
//This layer is used to discard modules             
//from the dijit package.      

{
			name: "../dijit/dijit.js",
			dependencies: 
[
				"dijit.dijit",  
                    "dijit.dijit-all"                                         

			],
			discard: true
		},
 //This layer is used to discard modules             
//from the dojox package

{
			name: "../dojox/dojox.js",
			dependencies: [
			//modules to be included from the dojox 
                                            //package, for example dojox.fx if  
                                            //this module is used in our code
                        ],
			discard: true
		},

	       

              //Custom layer mydojo.js which
              // includes our custom Dojo artifacts               
           {
              	//place the file under dojoRootDir 
              	name: "../../../mydojo.js",                                           
              	resourceName: "mydojo",
              	layerDependencies: 
[
                   	"dojo.js",                                           
                   	"../dijit/dijit.js",
                   	"../dojox/dojox.js"
               ],                                                                    
               dependencies: 
[
                               //modules to be included from the
                               //custom project. You can probably 
		  //list a single module here which in
		  //turn declares all the required
		  //modules as opposed to listing all the
		  //modules individually. Please take a 
		  //look at dojoRootDir/dojo/_base.js 
		  //file for an example.
                ]
             }
        ],

        prefixes: [
                         ["dijit", "../dijit"],
                         ["dojox", "../dojox"],
                         ["custom", "../custom"]
        ]
	
}

Note: The modules specified for the discard layers (the values given for the dependencies attribute for each layer) in Listing 4 may not eliminate all modules from the respective packages. For instance, the dojo.js layer in Listing 4 prevents all the Dojo base modules from being included but does not prevent modules, for instance, from the dojo.io package. This will not be a problem if your custom code does not require modules from the dojo.io package. If this is not the case, then the module will be included in your layer file, increasing the layer file size. So ensure that all modules that are to be excluded from your layer file are included in one of the discard layers.


Executing the build to create the layer file

With the profile created, you can now run the build tool as shown in Listing 5 to create the layer file.

Listing 5. Running the build tool to create your custom layer
./build.sh profileFile=<dojoRootDir>/myProf
         action=clean, release releaseName=myRelease.

The execution of the build in Listing 5 results in the creation of the layer file mydojo.js under the <dojoRootDir> directory. You can now copy this layer file to your Web server so that clients can download it.


Including your layer file from the client side

The clients who want to use the custom Dojo artifacts can now do so by referring to the created layer file as shown in Listing 6.

Listing 6. Code snippet illustrating how to download the layer file
<!--Load Dojo from the client site -->
<script type="text/javascript" 
src="<clientDojoRootDir>/dojo/dojo.js"></script>

<!—Now load our layer file -->
<script type="text/javascript" 
src="http://www.mysite.com/mydojo.js"></script>

Voila!! Now the clients can start using your custom Dojo artifacts with just a single request.


Potential issue

The integration is dependent on the client being responsible for providing the modules from the dojo/dojox/dijit packages. However, there is a high probability that the clients themselves have created a custom Dojo build. This means that they may not include certain modules in their layer files from the dojo/dojox/dijit packages. This can become a problem if the modules discarded from the client's layer files are required by your custom Dojo code.

This can be better understood with the following scenario.

Assume that your custom Dojo code has a dependency for the module dijit.ComboBox. Because this module is part of the Dijit package, it will not be included in your layer file. If the client is using custom layers that do not include dijit.ComboBox, then you probably might think that when the dojo.require("dijit.ComboBox") statement executes, the module will be explicitly downloaded. However, the issue here is that when the build runs, it removes all the dojo.require() statements from the layer. Therefore, the module is never loaded. This results in an error when the code that refers to this module is executed.

A solution for this is to identify such modules and add dojo.require() statements for these modules to the beginning of the layer file. This ensures that all these modules are loaded before they are referred.


Summary

I've demonstrated how to create a custom Dojo layer for the custom Dojo artifacts. Additionally, I've shown how to further optimize this layer file by ensuring that it does not include any modules from the Dojo/Dijit/Dojox packages, as these modules will be available at the site that deploys your layer file. I also described a potential issue with this integration and explained how to overcome it.


Download

DescriptionNameSize
Sample downloadSampleCode.zip2KB

Resources

Learn

Get products and technologies

  • Download the latest version of Dojo from the project Web site. (The source builds are suffixed with "-src")

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 Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=445595
ArticleTitle=Create optimized Dojo builds for your custom Dojo artifacts
publish-date=11102009