Comment lines by Kevin Haverlock: Using Ant and ShrinkSafe to improve performance of Web applications that use Dojo

One of the easiest ways to increase the performance of complex Dojo widgets is to use a profile build. This article explains how to use the Ant build utility together with Dojo’s ShrinkSafe to automate the profile build, resulting in improved performance of your Dojo-based Web pages. This content is part of the IBM WebSphere Developer Technical Journal.

Share:

Kevin Haverlock (kbh@us.ibm.com), Software Developer, IBM

Author photoKevin Haverlock is a software engineer for IBM in Research Triangle Park, NC. He has worked on various portions of WebSphere Application Server dating back to 5.0. His most recent assignment was the Web 2.0 Feature Pack for WebSphere. Kevin is currently working on web development tooling to help customers enhance their serviceability of WebSphere Application Server.


developerWorks Contributing author
        level

03 March 2010

Also available in Chinese Spanish

Dojo vu

When I talk to developers about the Dojo JavaScript™ toolkit, the conversation invariably turns to performance. The discussion usually includes comments like this:

"I like the widget I built, but it takes forever to load. I look in the debugger, and it seems to want to load a ton of JavaScript."

Indeed, prior to optimization, I've seen where the performance of a page I was developing would load in under two seconds, but the load time would degrade to almost 30 seconds when the server was located across the Atlantic.

The reason for this is that the Dojo JavaScript library is modular. As a Dojo developer, you select the components you want to utilize and only load those components. When it loads your page, the Dojo JavaScript parser will go back to the server and pull down the Dojo components that it needs, thus increasing the round trip time between the server and the client.

The components that are initially loaded can be seen in the dojo.require clauses for your code, similar to those shown in Listing 1.

Listing 1
<script>  
  dojo.require("extensions.movepage.MovePageTree");  
  dojo.require("dojox.data.FileStore");
  dojo.require("dijit.layout.ContentPane");
  dojo.require("dijit.TitlePane");  
  dojo.require("dijit.form.Button");
  dojo.require("dijit.form.RadioButton");
  dojo.require("dijit.layout.ContentPane");
  dojo.require("dijit.form.ValidationTextBox");
  dojo.require("dojox.collections.ArrayList");
  dojo.require("dojox.form.FilePickerTextBox");
</script>

The solution is a profile build of Dojo -- which should be considered the lowest hanging fruit when it comes to improving Dojo performance on your software project. I want to take this opportunity to explain a profile build and layout a build process using Ant. The Ant build can be used as part of an automated build of your code, or it can be built within your Eclipse development environment. I'll address the scenario where you want to build a WAR file that contains Dojo along with an optimized profile for the widgets you are creating.


Optimizing with ShrinkSafe compression

ShrinkSafe is a wonderful little utility that is provided with the Dojo toolkit and acts as a compression utility for your JavaScript code. Instead of having multiple Dojo JavaScript files being loaded, ShrinkSafe will compress the files into one JavaScript file that can be loaded by the widget you created. Additionally, ShrinkSafe removes comment lines and shortens variable names to save space and further decrease the size of the download. By loading just one JavaScript file containing your Dojo components, you reduce the number of HTTP requests that are needed to load your page. The resulting process of optimization is often called a Dojo profile build.

ShrinkSafe is configured by creating a profile and telling the utility what files to compress and the expected output file name. The file is created using a JSON format.

The first step is to look at the widget you have created and figure out what needs to be optimized. A good starting point is the components shown in the dojo.require section. Similar to Listing 1, you will want to take the components and place them in your profile file.

Listing 2 shows an example profile after you add your dojo.requires. In this case, the name of the widget you are creating is extensions.movepage.MovePageTree. When putting together your profile, consider using a debugger such as Firebug to see what else Dojo might be loading for the widget and can also be included in the profile.

Listing 2
dependencies = { 
   "layers" : [ { 
   "name" : "MovePageTree_profile.js",
   "dependencies" : [ "dijit.form.Button",
                      "dijit.form.CheckBox",
                      "dojox.form.FilePickerTextBox", 
                      "dijit.form.RadioButton",
                      "dijit.form.ValidationTextBox", 
                      "dijit.layout.ContentPane",
                      "dijit.TitlePane",
                      "dijit.Tooltip",
                      "dijit.Tree", 
                      "dojox.collections.ArrayList", 
                      "dojox.data.FileStore",                        
                      "extensions.movepage.MovePageTree" ]	        
	    }],
	    "prefixes" : [ [ "dijit", "../dijit" ], 
	                   [ "dojox", "../dojox" ], 
	                   [ "extensions",   "../../AEXUIWEB/WebContent/extensions" ] ]
	                   };

After you have your ShrinkSafe profile created, you'll need to create the Ant build script. The sample Ant build here will:

  1. Uncompress the Dojo Toolkit, including the ShrinkSafe utility, into your build directory.
  2. Fork a Java™ process to start ShrinkSafe and pass the configuration parameters.
  3. Copy files, including the ShrinkSafe output, to the Web-Content directory.
  4. Use the Ant WAR task to create a Web archive (WAR) file.

Let's look at these steps a little closer.

In step 1, you start by using the Dojo Toolkit dojo-release-1.4.1-src.zip (available from the dojotoolkit.org Web site or available with the IBM® WebSphere® Application Server Feature Pack for Web 2.0). The download includes the ShrinkSafe utility. You uncompress the file in a temporary build directory. Once uncompressed, the build directory will contain the Dojo toolkit as well as the ShrinkSafe utility. This is shown in Listing 3.

Listing 3
<!-- unzip the Dojo distribution  -->    
<unzip dest="${basedir}/build/profile/">
  <fileset dir="${basedir}/utils/" includes="*.zip"/>
</unzip>

Listing 4 shows step 2. The Ant task starts a Java JVM using the <java> Ant task. Before starting ShrinkSafe, you set the classpath as well as pass in additional arguments. One of the arguments is the location of your profile that tells the ShrinkSafe utility what files to compress and the output. The profile passed is the one you created in Listing 2.

Listing 4
<!-- Start the profile build by forking a java process to run ShrinkSafe -->
<java fork="true"
      dir="${dir.profile}/util/buildscripts"
      classname="org.mozilla.javascript.tools.shell.Main">
 <classpath>
   <pathelement location="${dir.profile}/util/shrinksafe/js.jar"/>
   <pathelement     location="${dir.profile}/util/shrinksafe/shrinksafe.jar"/>
</classpath>
   <arg value="${dir.profile}/util/buildscripts/build.js"/>
   <arg value="version=1.4.1-demo"/>
   <arg value="profileFile=${basedir}/profiles/aexdojo.profile.js"/>
   <arg value="action=release"/>
   <arg value="optimize=shrinksafe"/> 
   <arg value="cssOptimize=comments.keepLines"/>
</java>

In step 3, you copy the output from ShrinkSafe into the WebContent directory. The WebContent directory will contain files that make up your WAR file. The copy runs the util directory which contains the ShrinkSafe utility itself. This is shown in Listing 5.

Listing 5
 <copy toDir="${basedir}/WebContent/">
    <fileset dir="${dir.profile}/release/dojo" excludes="**/util/**" />
    </copy>

Finally, in step 4 (Listing 6), you use the Ant <war> task to create a WAR file. The WAR file contains everything in the WebContent directory, including the web.xml. The WAR file is called DojoWEB.war. You may also want to include any other files that should also be part of your WAR file.

Listing 6
<war destfile="${dir.dist}/DojoWEB.war" >
 <zipfileset dir="${basedir}/WebContent/" includes="**/**" prefix="" /> 
</war>

Once you have your profile created, remember to add the JavaScript code to your widget so the optimized code generated by ShrinkSafe can be loaded. Listing 7 assumes the profile build is called MovePageTree_profile.js. The profile build file needs to be located before the dojo.require clause so that the Dojo parser will load the JavaScript file before trying to load the other Dojo components.

Listing 6
<--  Load the JavaScript generated by ShrinkSafe first -->
<script type="text/javascript" src="/dojo/dojo/MovePageTree_profile.js"></script>

<script>  
  dojo.require("extensions.movepage.MovePageTree");
  dojo.require("extensions.movepage.TreeFileStore");
  dojo.require("dojox.data.FileStore");
  dojo.require("dijit.layout.ContentPane");
  dojo.require("dijit.TitlePane");  
  dojo.require("dijit.form.Button");
  dojo.require("dijit.form.RadioButton");
  dojo.require("dijit.layout.ContentPane");
  dojo.require("dijit.form.ValidationTextBox");
  dojo.require("dojox.collections.ArrayList");
  dojo.require("dojox.form.FilePickerTextBox");

</script>

Listing 8 shows the completed Ant script example.

Listing 8
<project name="DojoWAR" default="production" basedir=".">

 <!-- The directory where build artifacts are created -->
  <property name="dir.build" location="build"/>
	
 <!-- The directory where the war file will be placed -->
 <property name="dir.dist"  location="${dir.build}/dist"/>
 
 <target name="production" depends="buildDojoProfile, generateDistributable"/>
   
 <target name="generateDistributable"
  description="Builds the distributable Dojo War file">

  <!-- Build up the WAR  -->
  <mkdir dir="${basedir}/temp"/>
  <mkdir dir="${basedir}/build/dist"/>
     
  <war destfile="${dir.dist}/DojoWEB.war" >
    <zipfileset dir="${basedir}/WebContent/" includes="**/**" />
  </war>     
   
 </target>

 <target name="buildDojoProfile">
   <property name="dir.profile" 
	location="${basedir}/build/profile/dojo-release-1.4.1-src"/>
  	
  <echo message="Building Dojo profile..."/>
  	
  <!-- unzip the Dojo distribution -->
  <unzip dest="${basedir}/build/profile/">
    <fileset dir="${basedir}/utils/" includes="*.zip"/>
  </unzip>
  	
  <!-- Start the profile build by forking a java process to run ShrinkSafe -->
  <java fork="true"
     dir="${dir.profile}/util/buildscripts"
     classname="org.mozilla.javascript.tools.shell.Main">
    <classpath>
      <pathelement location="${dir.profile}/util/shrinksafe/js.jar"/>
      <pathelement location="${dir.profile}/util/shrinksafe/shrinksafe.jar"/>
    </classpath>
    <arg value="${dir.profile}/util/buildscripts/build.js"/>
    <arg value="version=1.4.1-demo"/>
    <arg value="profileFile=${basedir}/profiles/aexdojo.profile.json"/>
    <arg value="action=release"/>
    <arg value="optimize=shrinksafe"/> 
    <arg value="cssOptimize=comments.keepLines"/>
  </java>
  <!-- remove unused Dojo files and directories -->  
  <!-- that we don't want to include            -->
  	 
    <delete includeemptydirs="true">
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/tests/**/"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/demos/**/"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="util/**"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/*.psd"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/*.fla"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/*.svg"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/*.as"/>
        <fileset dir="${dir.profile}/release/dojo/dojo" includes="**/*.swf"/>
        <fileset dir="${dir.profile}/release/dojo/dijit/themes/" 
		includes="**/themeTester*"/>
        <fileset dir="${dir.profile}/release/dojo/" includes="**/*.uncompressed.js"/>
     </delete>  	

 <copy toDir="${basedir}/WebContent/">
   <fileset dir="${dir.profile}/release/dojo" excludes="**/util/**" />
 </copy>    
</target>

<!-- Simple cleanup -->
  <target name="clean" description="Cleans out build files">
    <delete dir="${dir.build}"/>   	
  	<delete dir="${basedir}/WebContent/dijit"/> 
	<delete dir="${basedir}/WebContent/dojo"/> 
  	<delete dir="${basedir}/WebContent/dojox"/>  	
  	<delete file="${basedir}/WebContent/dojo_extraction_revision.txt"/>
  	<delete file="${basedir}/WebContent/dojo_extraction.log"/>
  	<delete file="${basedir}/WebContent/version.txt"/>  	
  </target>
</project>

Summary

This article showed you how to use ShrinkSafe combined with Ant to create an optimized build of Dojo components that your Dojo widget might be using. The optimized build results in increased performance of your Web pages along with leveraging Ant so that you can automate your builds and Dojo optimizations.

Resources

Learn

Get products and technologies

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
ArticleID=470617
ArticleTitle=Comment lines by Kevin Haverlock: Using Ant and ShrinkSafe to improve performance of Web applications that use Dojo
publish-date=03032010