Develop lightweight mobile web applications with Dojo Mobile

Optimization and performance considerations

Dojo Mobile is a Dojo-based widget set for creating mobile web applications. With Dojo Mobile, you can develop lightweight, high-performance mobile web applications. In this article, learn how Dojo Mobile addresses the performance issues, and how you can optimize Dojo Mobile-based user applications to make them as small and efficient as possible. [Several clarifications have been made in the text to better reflect the author's original intent.]

Yoshiroh Kamiyama (kami@jp.ibm.com), Software Engineer, IBM

Photo of Yoshiroh KamiyamaYoshiroh Kamiyama is an Advisory Software Engineer at Yamato Software Lab (YSL), IBM Japan. He works on WebSphere Feature Pack for Web 2.0 and Mobile, and previously worked on several development projects including Mobile Mashup, Lotus iNotes, and Rational Portfolio Manager, many of which used the Dojo Toolkit. He is an original contributor of dojox.mobile and a committer to the Dojo Toolkit.



13 December 2011 (First published 18 November 2011)

Also available in Chinese Japanese Vietnamese

Introducing Dojo Mobile

Download and try the IBM Mobile Technology Preview

Get started building mobile applications that extend and integrate into the enterprise with the IBM Mobile Technology Preview. The code samples and services in the preview include a RESTful notification service; PhoneGap, an open source framework for building hybrid mobile apps; a lightweight WebSphere Application Server runtime; and sample code to let you see how it all works.

Most mobile phones on the market these days have full-featured web browsers that are almost indistinguishable from desktop browsers. These mobile web browsers can handle most of the recent web technologies such as HTML5, CSS3, JavaScript, DOM manipulation, and Ajax.

The Dojo Toolkit has been evolving for desktop web application development, and Dojo can run on mobile web browsers as well. Since Dojo already provides numerous useful widgets, do we really need something special for mobile applications? Yes, for several reasons:

  1. Input device differences: Most mobile devices have no mouse or physical keyboard. Instead, they provide a touch screen that supports finger operations. User interactions on desktop applications—drag and drop operations, mouse hover actions, keyboard shortcuts and navigation (traversal using the TAB key or arrow keys), and so on—present a challenge on a mobile device. Any UI widgets for mobile should be touch-enabled.
  2. Smaller screen size: A mobile screen is small, and the user uses a finger on a touch screen. It is very important to properly design the UI for mobile. Also, the screen size of a tablet device is much bigger than a smartphone screen. Mobile web applications need a user interface that transforms according to the screen size or screen orientation.
  3. Performance issues: While processor power of mobile devices is increasing rapidly, they still have less computing power than desktop computers. Also, the mobile network bandwidth is much lower than that of a desktop; sometimes it's extremely lower. Mobile web applications should be extremely small-footprint and high-performing.

Get the IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile

IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile includes the IBM Dojo 1.7 Toolkit, new mobile and rich Internet application (RIA) building blocks, and a Dojo-based diagram component. With accompanying Rational tools, the Feature Pack helps you take WebSphere applications developed originally for desktop browsers and adapt and deploy them to mobile devices.

Dojo Mobile is a Dojo-based widget set for creating mobile web applications. It was introduced in Dojo 1.5 as dojox.mobile to address the above issues. The input device and screen size issues, however, could be solved with a traditional approach, that is, simply enhancing existing Dojo widgets by adding mobile support without reinventing the ones just for mobile. But obviously performance issues cannot be resolved that way. Therefore, one of the most important (and challenging) tasks for Dojo Mobile is tackling the performance issues, especially minimizing code size.


Image-free UI widgets

One of the interesting features of Dojo Mobile is that it does not use any images to build UI widgets. WebKit-based browsers, which are the most popular browsers on mobile devices, support CSS3. CSS3 features, such as gradient backgrounds, rounded corner boxes, and transformation of DOM elements, can handle graphical representation without using images. Figure 1 shows some of the UI widgets that Dojo Mobile provides. These widgets do not use images; instead, they use DOM elements like <div> with CSS styles to construct their UI. Using many images could increase the total download size and the number of HTTP requests to the server, causing performance degradation. Dojo Mobile avoids that by using CSS3 capability as much as possible.

Figure 1. Image-free Dojo Mobile widgets
Image-free Dojo Mobile widgets that have UIs

On the other hand, user applications may use images. Figure 2 shows examples that are provided as Dojo Mobile test files. As you can see, tab bar buttons, list item icons, and icon container icons are images. Overuse of images could degrade performance, but that is a choice for the application. Dojo Mobile itself does not use images, nor does it force the user application to use images. Furthermore, as you will see later, Dojo Mobile provides some useful mechanisms, such as DOM buttons and CSS sprite, which can reduce the need for images and reduce the number of HTTP requests to the server.

Figure 2. User application's images
Example images that are used from user applications

CSS Sprite

When image use is inevitable, there are two possible ways to minimize the performance degradation. One way is to reduce the file size of your images by reducing the number of colors or increasing the compression rate. The other way is to reduce the number of HTTP requests for images by aggregating multiple small images into a single big image. The combined big image can be clipped and adjusted with CSS properties so that it can be used as one of small images. This technique is known as CSS Sprite, and Dojo Mobile supports it.

Listing 1 shows an example of list items, each using a separate icon. Figure 3 shows the result. This example produces three HTTP requests for images.

Listing 1. List items with separate images
<ul dojoType="dojox.mobile.RoundRectList">
  <li dojoType="dojox.mobile.ListItem" icon="i-icon-1.png" moveTo="bar">General</li>
  <li dojoType="dojox.mobile.ListItem" icon="i-icon-2.png" moveTo="bar">Photos</li>
  <li dojoType="dojox.mobile.ListItem" icon="i-icon-3.png" moveTo="bar">Store</li>
</ul>
Figure 3. Result of Listing 1
Result of the list items with separate images

On the other hand, Listing 2 shows an example that uses an aggregated image (i-icon-all.png), which is shared by list items. By specifying comma-separated values (top,left,width,height) for the iconPos property of the ListItem widget, you can reuse any rectangle area of the aggregated image. As shown in Figure 4, the result is the same, but it produces only one HTTP request for the aggregated image.

Listing 2. List items with an aggregated image
<ul dojoType="dojox.mobile.RoundRectList" iconBase="i-icon-all.png">
  <li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" moveTo="bar">General</li>
  <li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" moveTo="bar">Photos</li>
  <li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" moveTo="bar">Store</li>
</ul>
Figure 4. Result of Listing 2
Result of the list items with an aggregated image

CSS Sprite can also be used for icon container's icons (Figure 5) or tab bar's buttons (Figure 6).

Figure 5. IconContainer with CSS Sprite
Icon container with CSS sprite
Figure 6. TabBar with CSS Sprite
Tab bar with CSS sprite

DOM Button

Dojo Mobile provides simple buttons, icons, check marks/arrows for a list item, and so on, as shown in Figure 7. They are made from <div> elements with CSS styles applied without images, and are called DOM Buttons.

Figure 7. DOM Buttons
DOM buttons

Ideally DOM Buttons are smaller in byte size, since they are made from CSS without images. Table 1 compares byte sizes of DOM Buttons and images using DomButtonGreenCircleArrow (fourth down, first column in Figure 7) as an example. You can see a DOM Button is much smaller than an image.

Table 1. Byte size comparison between a DOM Button and an image
FileByte size
DomButtonGreenCircleArrow.css (minified & gzipped)392 bytes
mblDomButtonGreenCircleArrow.png1,599 bytes

DOM Buttons have the additional advantage of not needing to make additional HTTP requests, because they can be integrated into a theme CSS file with the build tool. In this situation, the footprint of a DOM Button is much smaller. Table 2 shows a DOM Button's byte size in an aggregated CSS file. You can see the addition of DomButtonGreenCircleArrow.css increases by only 155 bytes.

Table 2. DOM Button's byte size in an aggregated CSS file
FileByte size
base.css (minified & gzipped)2,844 bytes
base.css + DomButtonGreenCircleArrow.css (minified & gzipped)2,999 bytes
Difference155 bytes

DOM Button structure

DOM Button consists of nested <div> elements with CSS styles applied. As mentioned, you can achieve a variety of graphical representations by using CSS3's rich capabilities, such as gradient backgrounds, rounded corner boxes, and transformation of DOM elements. You could even draw a circle by adjusting the border radius of a square <div> element. Figure 8 shows an example of DOM Button structure.

Figure 8. Structure of DOM Button
Structure of DOM button

How to use DOM Button

DOM Button is simply a collection of CSS styles. It does not require JavaScript code. It can be displayed by just placing nested <div> elements and applying CSS styles to them. Listing 3 shows the minimum sample code, and Figure 9 shows the result.

Listing 3. Use of DOM Button without JavaScript
<html>
  <head>
    <link href="themes/common/domButtons/DomButtonBlueCircleMinus.css" rel="stylesheet">
  </head>
  <body>
    <div class="mblDomButtonBlueCircleMinus">
      <div><div><div></div></div></div>
    </div>
  </body>
</html>
Figure 9. Result of Listing 3
Result of listing 3

In Listing 3, I prepared 4 levels of nested DIVs including the DOM Button's root node, which has a class name. However, the number of DIVs you need to prepare varies with the kind of DOM Button. To automatically create the necessary number of DIVs, use Dojo Mobile's dojox.mobile.createDomButton() function, as illustrated in Listing 4.

Listing 4. Use of DOM Button with JavaScript
<div id="btn1" class="mblDomButtonBlueCircleMinus"></div>
----
var node = dojo.byId("btn1");
dojox.mobile.createDomButton(node);

Listing 3 and Listing 4, however, are usually not used. I include them for illustrative purposes to show the mechanism of DOM Button. Instead, some of the Dojo Mobile widgets support DOM Buttons as below. You can specify DOM Buttons in place of image icons or buttons.

  • ListItem: icon, rightIcon, rightIcon2, arrowClass, and checkClass property (Figure 10)
  • TabBarButton: icon1 and icon2 property (Figure 11)
  • ToolBarButton: icon property (Figure 12)
  • TabBarButton: icon property (Figure 13)
Figure 10. ListItem (list)
list item
Figure 11. TabBarButton (tab bar)
tab bar button
Figure 12. ToolBarButton (heading)
tool bar button
Figure 13. TabBarButton (segmented control)
tab bar button

How to create a custom DOM Button

You can create your own custom DOM Buttons. Here are some tips.

  • The class name of a DOM Button MUST start with "mblDomButton". Dojo Mobile checks it to determine if it is a DOM Button or not. (On the other hand, a CSS file name and where to place it can be your choice.)
  • Specify the width and height of the DOM Button to its root node. They will be the size of the entire DOM Button.
  • <div> elements are nested, not siblings. Therefore, you may need to apply CSS styles to a node relative to its parent node.
  • To apply CSS styles to a specific <div> element in the <div> hierarchy, you can use a child selector (>).
  • If you want to support non-CSS3 desktop browsers, you should create an equivalent image and a compat css file (*-compat.css).

Listing 5 and Listing 6 show a custom DOM Button example. Figure 14 shows the result.

Listing 5. Custom DOM Button (DomButtonMyCheck.css)
/* === Red Check Button ==*/
.mblDomButtonMyCheck {
  position: relative;
  width: 29px;
  height: 29px;
}
.mblDomButtonMyCheck > div {
  position: absolute;
  left: 0px;
  top: 8px;
  width: 16px;
  height: 6px;
  font-size: 1px;
  -webkit-transform: scaleX(0.7) rotate(135deg);
  border-width: 3px 4px 0px 0px;
  border-style: solid;
  border-color: red;
}
Listing 6. Custom DOM Button (DomButtonMyCheck-compat.css)
/* === Red Check Button ==*/
.mblDomButtonMyCheck {
	background-image: url(compat/mblDomButtonMyCheck.png);
	background-repeat: no-repeat;
}
.mblDomButtonMyCheck > div {
	display: none;
}
Figure 14. Custom DOM Button
custom DOM button

Compatibility module

Dojo Mobile is optimized for WebKit-based mobile browsers, but it supports non-WebKit desktop browsers as well. However, no one wants to sacrifice performance on mobile devices to support desktop browsers. Cross-browser support code should not be loaded when an application runs on mobile devices.

Conditional compilation

One approach is conditional compilation, which allows you to strip out some code blocks that are unnecessary for mobile. Dojo provides two ways of conditional compilation, pragmas and has().

Pragmas are special directives that can be used to exclude/include some parts of the code as shown in Listing 7.

Listing 7. Example of pragma usage
process: function(){
//>>excludeStart("marker1", kwArgs.noIE);
    if(dojo.isIE){
        ....
    }
//>>excludeEnd("marker1");
    ....
}

In the above example, if you build the code with the noIE=true condition option specified as below, the code block surrounded by excludeStart and excludeEnd is removed from the build.

> build profile=myapp action=release noIE=true

Also, if you use includeStart/includeEnd pragmas, the surrounded code block is included only when the condition matches.

has() (or dojo/has, or has.js) is a feature detection/testing mechanism, introduced in Dojo 1.7. As shown in Listing 8, you can use it to test whether or not a specific feature exists in the current runtime environment.

Listing 8. Example of "has" test
process: function(){
    if(has("ie")){
        ....
    }
    ....
}

If you configure the staticHasFeatures array in your build profile as below, has("ie") is replaced with 0, and then the compiler's optimizer detects its code block as dead code, and the block is removed from the build.

staticHasFeatures: {
  'ie': 0
}

Compatibility module

Conditional compilation allows you to make a build that is optimized for a specific platform. The build, however, has a problem in that it does not work on other platforms. To support other platforms, you need to make other builds. To solve this issue, Dojo Mobile took a different approach: the compatibility module (or compat).

Compat includes some code that supports non-WebKit browsers. If compat is loaded, it "overwrites" some of the widget methods that need to be fixed. Overwriting the code keeps the original widget class names the same and therefore does not affect the user's application code. On the other hand, overriding the code by subclassing the original widgets would require the use of newly defined widget class names. Compat also loads *-compat.css files, which are patches to the original css files. In the compat mode, traditional techniques are used to render the widget UIs without CSS3, such as JavaScript-based animations with dojo.fx, background images, and so on. To use compat for your application, load "dojox.mobile.compat" using dojo.require() or the require API.

Note that compat is divided into two pieces, compat.js and _compat.js. _compat.js includes all the implementation code, and compat.js is a loader of _compat.js. compat.js loads _compat.js only when the current browser is not WebKit-based. compat.js is such a tiny piece of code that it does not affect mobile performance even if it is in a build. This way, on WebKit-based browsers, performance does not degrade since _compat.js will never be loaded. On non-WebKit browsers, _compat.js is loaded automatically, and Dojo Mobile works in the compat mode. Table 3 shows byte size comparison between a mobile build without compat and a mobile build with compat. As you can see, the difference is negligibly small: 45 bytes.

Table 3. Mobile build size comparison (profile: mobile-all.profile.js, minified & gzipped)
DescriptionByte size
Mobile build without compat36,594 bytes
Mobile build with compat36,639 bytes
Difference45 bytes

Performance evaluation tips

As described above, on non-WebKit browsers, Dojo Mobile runs in the compat mode, and additional resources, such as images and/or *-compat.css, are loaded. So, if you want to evaluate which and how many files are loaded in a mobile device, you should not use non-WebKit browsers such as Firefox or Internet Explorer. Debuggers on Google Chrome or the desktop version of Safari are better tools to monitor the network traffic for that purpose, since they are WebKit-based.


Module dependencies

Dojo provides a lot of useful APIs, and they are packaged as modules, which are relatively small JavaScript files. There are countless useful modules available. However, overusing them could result in a very big footprint. Dojo Mobile is carefully designed to have as little module dependencies as possible. For example, it intentionally does not use some of the commonly used, useful modules like dojo.query or dijit._Templated. Also, all the Dojo Mobile widgets inherit from dijit._WidgetBase rather than dijit._Widget. dijit._WidgetBase is a base class of dijit._Widget, and does not include some of the code that is unnecessary for mobile, such as keyboard support code, and therefore it is lighter than dijit._Widget. Also, it does not use dijit._base.manager, which was a required module until Dojo 1.6; instead, it uses dijit.registry, which is a subset of dijit._base.manager.

Use of dojo modules like dojo.query or dijit._Templated from Dojo Mobile based user applications is of course your choice. However, you should carefully choose which dojo/dijit modules to use based on performance. For example, if you use dojo.query only once in your application, you could replace it with far smaller code than the entire dojo.query implementation.

Listing 9 shows the modules on which the Dojo Mobile base depends directly or indirectly. You may notice it has fewer dependencies on dojo/dijit modules than typical desktop use cases. It depends on only 11 dojo/_base modules out of 25, and has no dependency on the dijit/_base modules. If you use additional modules that are not shown in Listing 9, that increases your application's footprint. When you use such modules, you should choose them carefully.

Listing 9. Dependent modules
dijit/_Contained
dijit/_Container
dijit/_WidgetBase
dijit/main
dijit/registry
dojo/Evented
dojo/Stateful
dojo/_base/Deferred
dojo/_base/array
dojo/_base/config
dojo/_base/connect
dojo/_base/declare
dojo/_base/event
dojo/_base/kernel
dojo/_base/lang
dojo/_base/sniff
dojo/_base/unload
dojo/_base/window
dojo/aspect
dojo/dom
dojo/dom-attr
dojo/dom-class
dojo/dom-construct
dojo/dom-geometry
dojo/dom-prop
dojo/dom-style
dojo/domReady
dojo/has
dojo/keys
dojo/mouse
dojo/on
dojo/ready
dojo/topic

Build

To optimize the load time performance, build is an important process. Dojo has a powerful build system, which compresses all your JavaScript and CSS into fewer files and creates an efficient version of your application for release. Figure 15 and Figure 16 show transferred files comparison between a non-built (source code) application and a built application. You can see there is a huge difference in the number of requests and the total transferred size. The next section discusses building Dojo Mobile.

Figure 15. The number of requests and download size (non-built)
The number of requests and download size (non-built)
Figure 16. The number of requests and download size (built)
The number of requests and download size (built)

customBase build

Dojo build has an option called customBase. The standard Dojo build includes most of the Dojo base modules in a build, since the Dojo base modules are always available without explicitly requiring them. However, if you make a build with the customBase option enabled, only the modules that are in the actual dependency chain are included in the build. Dojo Mobile is designed to have as few Dojo base module dependencies as possible. Therefore, to benefit from the design, the use of the customBase option is important. Listing 10 shows how to specify the customBase option in your build profile.

Listing 10. customBase option in a profile file
dependencies = {
  stripConsole: "normal",

  layers: [
    {
      name: "dojo.js",
      customBase: true,
      dependencies: [
        "dojox.mobile.parser",
        "dojox.mobile",
        "dojox.mobile.compat"
      ]
    },
  ....

Closure compiler

There are two compilers (or compressors) that can be used form the Dojo build tool, Shrinksafe and Google Closure Compiler. Shrinksafe is Dojo's default compiler. Closure has been bundled with Dojo since version 1.7. Table 4 shows mobile build size comparison between Shrinksafe and Closure. As you can see, Closure's compression rate is better than Shrinksafe's, and the size of the Closure build is 20% smaller than that of the Shrinksafe build, at least in this example.

Table 4. Mobile build size comparison between Shrinksafe and Closure
DescriptionByte size
Mobile build (Shrinksafe, gzipped)44,826 bytes
Mobile build (Closure, gzipped)36,639 bytes

Dojo Mobile has been tested against what was built with Closure. Closure is recommended to use for mobile build, since its output is smaller.

How to build Dojo Mobile

Dojo Mobile provides two sample profile files: mobile-all.profile.js and mobile.profile.js, which are in the dojo/util/buildscripts/profiles folder. To easily build with these profiles, use the simple batch files available in the dojox/mobile/build folder.

From the command line, you can run the batch file. Use build.bat for Windows, or build.sh for Linux.

Listing 11. Usage of build batch file
  > build
  Usage: build separate|single [webkit]
    separate  Create mobile.js that includes only dojox.mobile
    single    Create a single dojo.js layer that includes dojox.mobile
    webkit    Enable webkitMobile=true option (Loses PC browser support)

separate uses mobile.profile.js and creates mobile.js that includes ONLY the dojox.mobile base modules. It does not include the dojo base or the dijit base modules. _compat.js is also created for desktop browser support. Also, dojo.js is created, but it is an ordinary dojo base build, not a customBase build.

Note that "the dojox.mobile base" does not include all the Dojo Mobile widgets. For example, ScrollableView, Carousel, SpinWheel, form controls, etc. are not included in the base. If you want them in your build, you can simply add them in the dependencies array in a profile file. Listing 12 shows all the modules that are rolled into the dojox.mobile base build, mobile.js.

Listing 12. Modules in mobile.js
dojox/main
dojox/mobile
dojox/mobile/EdgeToEdgeCategory
dojox/mobile/EdgeToEdgeList
dojox/mobile/Heading
dojox/mobile/ListItem
dojox/mobile/ProgressIndicator
dojox/mobile/RoundRect
dojox/mobile/RoundRectCategory
dojox/mobile/RoundRectList
dojox/mobile/Switch
dojox/mobile/ToolBarButton
dojox/mobile/TransitionEvent
dojox/mobile/View
dojox/mobile/ViewController
dojox/mobile/_ItemBase
dojox/mobile/_base
dojox/mobile/common
dojox/mobile/compat
dojox/mobile/sniff
dojox/mobile/transition
dojox/mobile/uacss

single uses mobile-all.profile.js and creates a single dojo.js layer that includes dojox.mobile base and all the dependent dojo/dijit modules. _compat.js is also created for desktop browser support. This build enables the customBase option. So, only the minimum dojo/dijit base modules are included in the resulted dojo.js. Listing 13 shows all the modules that are rolled into the single build.

Listing 13. Modules in dojo.js
dijit/_Contained
dijit/_Container
dijit/_WidgetBase
dijit/main
dijit/registry
dojo/Evented
dojo/Stateful
dojo/_base/Deferred
dojo/_base/array
dojo/_base/config
dojo/_base/connect
dojo/_base/declare
dojo/_base/event
dojo/_base/kernel
dojo/_base/lang
dojo/_base/sniff
dojo/_base/unload
dojo/_base/window
dojo/aspect
dojo/dom
dojo/dom-attr
dojo/dom-class
dojo/dom-construct
dojo/dom-geometry
dojo/dom-prop
dojo/dom-style
dojo/domReady
dojo/has
dojo/keys
dojo/mouse
dojo/on
dojo/ready
dojo/topic
dojox/main
dojox/mobile
dojox/mobile/EdgeToEdgeCategory
dojox/mobile/EdgeToEdgeList
dojox/mobile/Heading
dojox/mobile/ListItem
dojox/mobile/ProgressIndicator
dojox/mobile/RoundRect
dojox/mobile/RoundRectCategory
dojox/mobile/RoundRectList
dojox/mobile/Switch
dojox/mobile/ToolBarButton
dojox/mobile/TransitionEvent
dojox/mobile/View
dojox/mobile/ViewController
dojox/mobile/_ItemBase
dojox/mobile/_base
dojox/mobile/common
dojox/mobile/compat
dojox/mobile/parser
dojox/mobile/sniff
dojox/mobile/transition
dojox/mobile/uacss

webkit enables the webkitMobile=true build option, which strips out code chunks that are not necessary for Webkit-based mobile browsers. For example, Internet Explorer- or Firefox-specific code is excluded from the build. This reduces the total code size, but the built module will not work on desktop browsers even with the compatibility module (compat.js).

Also note that this option reduced a significant amount of code in Dojo 1.6, but in Dojo 1.7, feature detection/testing is moving to dojo.has, and thus the webkitMobile option no longer has much effect on code reduction.


CSS aggregation

Dojo Mobile has bunch of CSS files under the themes folder. There is a CSS file for each widget, and they are available for each theme, Android, Blackberry, Custom, and iPhone. Also, there are CSS files for DOM Buttons or transition animations. To help you easily include necessary CSS files in your application, some entry point CSS files aggregate a number of related CSS files:

  • All-in-one theme file (example: themes/iphone/iphone.css)
    Includes all the common CSS files and the theme CSS files
  • Base theme file (example: themes/iphone/base.css)
    Includes theme CSS files for dojox.mobile base modules
  • DOM Buttons (themes/common/domButtons.css)
    Includes all the DOM Buttons
  • Transitions (themes/common/transitions.css)
    Includes all the transition animations

Use of the all-in-one theme file is the easiest, since it includes everything. However, that means unused CSS files may be included, and that could increase footprint unnecessarily. In that case, one approach is to use the base theme file and individual CSS files that are not included in the base theme file.

The above entry point CSS files are a collection of @import directive. If you perform Dojo build, @import statements are inlined and thus the referenced CSS files are combined together in the entry point CSS file. So, use of one entry point CSS file produces only one HTTP request, if it is built. However, if you listed CSS files in your application using <link> or @import as shown in Listing 14, HTTP requests would be made for each of them.

Listing 14. Link tags in html (userApp.html)
<head>
  <link href="../themes/iphone/base.css" rel="stylesheet">
  <link href="../themes/iphone/TabBar.css" rel="stylesheet">
  <link href="../themes/common/SpinWheel.css" rel="stylesheet">
  <link href="../themes/common/domButtons/DomButtonBlueCircleArrow.css" rel="stylesheet">
  ....

To reduce the number of requests, create your own entry point CSS that has references to the minimum necessary CSS files using the @import directive as shown in Listing 15. If you perform a Dojo build, it will be an inlined CSS file without external references. You can use it from your application as shown in Listing 16.

Listing 15. A CSS file for aggregation (myStyles.css)
@import url("../themes/iphone/base.css");
@import url("../themes/iphone/TabBar.css");
@import url("../themes/common/SpinWheel.css");
@import url("../themes/common/domButtons/DomButtonBlueCircleArrow.css");
Listing 16. A single link tag in html (userApp.html)
<link href="myStyles.css" rel="stylesheet">

As described above, you can reduce the number of HTTP requests for CSS files by creating your own entry point CSS file and perform Dojo build.


Dynamic creation and lazy loading

Lazy loading—a technique to load modules only when they are referenced for the first time—improves the application's startup performance. Dojo Mobile itself uses the lazy loading technique internally.

Creating a view dynamically

With the url property of _ItemBase, you can dynamically create a new view immediately before making a view transition. Listing 17 shows an example usage of the url property. The view content can either be an HTML fragment (Listing 18) or JSON data (Listing 19).

Listing 17. Example of the url property
<ul dojoType="dojox.mobile.RoundRectList">
  <li dojoType="dojox.mobile.ListItem" url="view1.html">
    External View #1 (sync)
  </li>
  <li dojoType="dojox.mobile.ListItem" url="view2.json" sync="false">
    External View #2 (async)
  </li>
</ul>
Listing 18. An HTML fragment for a dynamic view (view1.html)
<div dojoType="dojox.mobile.View">
  <h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="foo">view1.html</h1>
  <ul dojoType="dojox.mobile.EdgeToEdgeList">
    <li dojoType="dojox.mobile.ListItem">
      Jack Coleman
    </li>
    <li dojoType="dojox.mobile.ListItem">
      James Evans
    </li>
    <li dojoType="dojox.mobile.ListItem">
      Jason Griffin
    </li>
  </ul>
</div>
Listing 19. JSON data for a dynamic view (view2.json)
{
  "dojox.mobile.View": {
    "dojox.mobile.Heading": {
      "@back": "Home",
      "@moveTo": "foo",
      "@label": "view1.json"
    },
    "dojox.mobile.EdgeToEdgeList": {
      "dojox.mobile.ListItem": [{
        "@label": "Jack Coleman"
      }, {
        "@label": "James Evans"
      }, {
        "@label": "Jason Griffin"
      }]
    }
  }
}

Another option is to programmatically fetch view content and insert it in the target view. Listing 20 shows an example.

Listing 20. Example of loading content into an existing view and making a transition
<li dojoType="dojox.mobile.ListItem" moveTo="#" onclick="myAction2(this)">
  Load and Move (async)
</li>
----
function myAction2(li){
   var view2 = dijit.byId("view2"); // destination view
   var listItem = dijit.byNode(li);
   var prog = dojox.mobile.ProgressIndicator.getInstance();
   dojo.body().appendChild(prog.domNode);
   prog.start();
   view2.destroyDescendants();

   var url = "http://..."; // or var url = listItem.url;
   dojo.xhrGet({
       url: url,
       handleAs: "text",
       load: function(response, ioArgs){
           var container = view2.containerNode;
           container.innerHTML = response;
           dojo.parser.parse(container);
           prog.stop();
           listItem.transitionTo("view2");
       }
   });
}

See dojox/mobile/tests/test_list-actions.html for details and more examples.

Lazy-load with IconContainer

IconContainer can have multiple icons, each of which represents a sub application. The sub applications may consist of one or more Dojo widgets. Loading of all the sub application code at startup could slow down the startup time of the main application. To improve the startup time performance, you can specify the lazy="true" parameter on IconItems. Then the Dojo parser skips instantiation of widgets inside IconItem, and IconContainer loads those icon content modules dynamically and instantiates them only when an icon is opened for the first time.

Listing 21 is an example of lazy loading of icon contents. Note that you do not have to explicitly require icon content modules (dijit.CalendarLite in the following example). Note also that, in Dojo 1.7, lazy loading is supported only in the sync loader mode, since lazy loading is performed synchronously using dojo.require.

Listing 21. Example of IconContainer's lazy load
<ul dojoType="dojox.mobile.IconContainer">
  <li dojoType="dojox.mobile.IconItem" label="Calendar" lazy="true">
    <div id="cal" dojoType="dijit.CalendarLite"></div>
  </li>
  ....
Figure 17. IconContainer
icon container

Lazy load with TabBar

If you need lazy-loadable tab panels, you can use the TabBar widget and the same technique as described in "Creating a view dynamically." For tab panels, you also need a little trick for the first tab panel, because there is no view transition at startup. You need to programmatically make a view transition from a dummy blank view to the first tab panel at startup to load external contents into the first tab panel. Listing 22 and Listing 23 show the same examples; the former is a sync example, the latter is an async example.

Listing 22. Example of lazy tab panels (sync mode)
  <script src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
  <script language="JavaScript" type="text/javascript">
    dojo.require("dojox.mobile");
    dojo.require("dojox.mobile.parser");
    dojo.require("dojox.mobile.compat");
    dojo.require("dojox.mobile.TabBar");
    dojo.ready(function(){
      setTimeout(function(){
        dijit.byId("tab1").onClick();
      }, 0);
    });
  </script>
</head>
<body style="visibility:hidden;">
  <ul dojoType="dojox.mobile.TabBar" barType="segmentedControl">
    <li id="tab1" dojoType="dojox.mobile.TabBarButton" url="view1.html">New</li>
    <li id="tab2" dojoType="dojox.mobile.TabBarButton" url="view2.html">What's Hot</li>
    <li id="tab3" dojoType="dojox.mobile.TabBarButton" url="view3.html">Genius</li>
  </ul>

  <div id="blank" dojoType="dojox.mobile.View" selected="true"></div>
  <div id="view1" dojoType="dojox.mobile.View"></div>
  <div id="view2" dojoType="dojox.mobile.View"></div>
  <div id="view3" dojoType="dojox.mobile.View"></div>
</body>
Listing 23. Example of lazy tab panels (async mode)
  <script src="../../../dojo/dojo.js" djConfig="async: true, parseOnLoad: true"></script>
  <script language="JavaScript" type="text/javascript">
  require([
    "dojo/_base/kernel",
    "dijit/registry",
    "dojox/mobile",
    "dojox/mobile/compat",
    "dojox/mobile/parser",
    "dojox/mobile/TabBar"
  ], function(dojo, registry){
    dojo.ready(function(){
      setTimeout(function(){
        registry.byId("tab1").onClick();
      }, 0);
    });
  });
  </script>
</head>
<body style="visibility:hidden;">
  <ul dojoType="dojox.mobile.TabBar" barType="segmentedControl">
    <li id="tab1" dojoType="dojox.mobile.TabBarButton"
        url="view1.html" sync="false">New</li>
    <li id="tab2" dojoType="dojox.mobile.TabBarButton"
        url="view2.html" sync="false">What's Hot</li>
    <li id="tab3" dojoType="dojox.mobile.TabBarButton"
        url="view3.html" sync="false">Genius</li>
  </ul>

  <div id="blank" dojoType="dojox.mobile.View" selected="true"></div>
  <div id="view1" dojoType="dojox.mobile.View"></div>
  <div id="view2" dojoType="dojox.mobile.View"></div>
  <div id="view3" dojoType="dojox.mobile.View"></div>
</body>

Requiring modules dynamically

Requiring modules dynamically at runtime is a good idea, since it could improve the startup time performance. But there is one potential problem you need to be aware of. Take a look at Listing 24; it shows loading a Dojo module programmatically. It does work, but if you build Listing 24, the build tool automatically picks up the required module, and rolls it into a build, and thus dojo.require does nothing at runtime since the module has already been loaded at startup time.

Listing 24. Load a Dojo module programmatically (WRONG example)
myHandler: function(e){
  dojo.require("dijit.CalendarLite");
  var cal = new dijit.CalendarLite();
  ....
}

To avoid that issue, you could write dojo["require"] instead of dojo.require as shown in Listing 25.

Listing 25. Load a Dojo module programmatically (CORRECT example)
myHandler: function(e){
  dojo["require"]("dijit.CalendarLite");
  var cal = new dijit.CalendarLite();
  ....
}

If your application is using the async loader, the syntax differs as shown in Listing 26. But this is not a good example either, since the build tool picks up the specified module unexpectedly if you write the code this way.

Listing 26. Load a Dojo module programmatically (WRONG example)
myHandler: function(e){
  require(["dijit/CalendarLite"], lang.hitch(this, function(module){
    var cal = new module();
    ....
  }));
}

You can avoid the build problem by assigning the class name to a variable as shown in Listing 27.

Listing 27. Load a Dojo module programmatically (CORRECT example)
myHandler: function(e){
  var cls = "dijit/CalendarLite"; // assign to a variable so as not to be in the build
  require([cls], lang.hitch(this, function(module){
    var cal = new module();
    ....
  }));
}

Asynchronous mode

In Dojo 1.7, a new AMD (Asynchronous Module Definition) loader is provided in addition to the traditional Dojo loader. Dojo Mobile widgets are written in the new AMD syntax. To load any Dojo modules, you can use either traditional dojo.require (Listing 28) or the new require API (Listing 29).

Listing 28. Example of dojo.require (traditional)
<script src="../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
<script language="JavaScript" type="text/javascript">
  dojo.require("dojox.mobile");
  dojo.require("dojox.mobile.parser");
  dojo.require("dojox.mobile.compat");
</script>
Listing 29. Example of require (AMD syntax)
<script src="../dojo/dojo.js" djConfig="async:true, parseOnLoad:true"></script>
<script language="JavaScript" type="text/javascript">
  require([
    "dojox/mobile",
    "dojox/mobile/parser",
    "dojox/mobile/compat"
  ]);
</script>

Listing 28 loads modules synchronously, while Listing 29 does it asynchronously. In circumstances where a lot of JavaScript files are loaded, it is expected that asynchronous loading will perform better than synchronous loading. If the JavaScript files are combined together into a single built file, however, there may not be much difference between synchronous and asynchronous.

However, there is a bigger difference you should be aware of. Figure 18 shows the transferred files when test_iPhone-Animation.html, which loads modules in the Listing 28 way, is opened, and Figure 19 shows the ones when test_iPhone-Animation-async.html, which loads modules in the Listing 29 way, is opened. As shown in the Table 5, in the sync mode, 17 more files, 26KB in total, are additionally loaded. This is because the sync mode works in the backward compatibility mode, and thus loads some required modules to keep backward compatibility. Given that test_iPhone-Animation-async.html works without those additional modules, it is obvious that they are not used, and do not have to be loaded. Therefore, even if you carefully choose what modules to use, and optimize your build using the customBase option, use of dojo.require() could derail your effort. You should use the require API rather than dojo.require() to optimize your application's performant.

Figure 18. Synchronous loading (test_iPhone-Animation.html)
Synchronous loading
Figure 19. Asynchronous loading (test_iPhone-Animation-async.html)
Asynchronous loading
Table 5. Resource download comparison between sync mode and async mode
FileNumber of requestsTotal size
test_iPhone-Animation.html2369.15 KB
test_iPhone-Animation-async.html643.54 KB

Incidentally, even if you use the AMD syntax like Listing 29, if you do not specify async:true (the default value is false), your application runs in the compatibility mode, and additional modules are loaded.


dojox.mobile.parser

dojox.mobile.parser is a small subset of dojo.parser. It was developed purely to reduce the total code size. It has no mobile-specific extra features over dojo.parser, so there is no reason you must use dojox.mobile.parser instead of dojo.parser; you can choose the one you like. Some of the advanced features of dojo.parser, such as <script type="dojo/method"> and <script type="dojo/connect">, are missing from dojox.mobile.parser. But dojox.mobile.parser is smaller.

As shown in Table 6, the size of dojox.mobile.parser is about 0.7KB (minified & gzipped), while dojo.parser (plus its dependent modules that are not required by the dojox.mobile base) is 6.5KB. If dojox.mobile.parser's capability is enough for your application, using it could reduce the total code size of your application.

Table 6. Size comparison between dojox.mobile.parser and dojo.parser
DescriptionByte size
dojox.mobile.parser734 bytes
dojo.parser + dependent modules6,507 bytes

Summary

This article has shown how to build lightweight mobile web applications using Dojo Mobile, and how to apply its performance-optimizing techniques to your applications.

Resources

Learn

Get products and technologies

  • Download the latest Dojo 1.7 from the Dojo Toolkit download page.
  • Download and try the IBM Mobile Technology Preview, a set of code samples and services to help you get started building mobile applications that extend and integrate into the enterprise. The preview includes a RESTful notification service; PhoneGap, an open source framework for building hybrid mobile apps; a lightweight WebSphere Application Server runtime; and sample code to let you see how it all works.
  • IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile includes the IBM Dojo 1.7 Toolkit, new mobile and rich Internet application (RIA) building blocks, and a Dojo-based diagram component. With accompanying Rational tools, the Feature Pack helps you take WebSphere applications developed originally for desktop browsers and adapt and deploy them to mobile devices.
  • Evaluate IBM products in the way that suits you best: Download a product trial, try a product online, use a product in a cloud environment, or spend a few hours in the SOA Sandbox learning how to implement Service Oriented Architecture efficiently.

Discuss

  • Get involved in the developerWorks community. Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.

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


  • Bluemix Developers Community

    Get samples, articles, product docs, and community resources to help build, deploy, and manage your cloud apps.

  • Mobile weekly

    Innovations in tools and technologies for mobile development.

  • DevOps Services

    Software development in the cloud. Register today to create a project.

  • IBM evaluation software

    Evaluate IBM software and solutions, and transform challenges into opportunities.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Mobile development, Web development, Open source
ArticleID=775773
ArticleTitle=Develop lightweight mobile web applications with Dojo Mobile
publish-date=12132011