General Interface is an open source project hosted by the Dojo Foundation

GI Build Tools - Creating a Build Optimized for Your App

Following up on my earlier post I want to go into much more detail on creating a build of GI that is optimized for a particular GI application. We highly recommend that you create an optimized build of GI for your critical applications. Creating an optimized build can dramatically shorten the initial load time of your application. I've seen 20 second load times reduced to 6 seconds just by deploying an optimized build.

Background

In the directory on your computer where you installed GI you have several things. The "GI runtime" consists of JSX/, jsx3.gui.window.* and logger.xml. The GI runtime is the platform that a GI application runs on. GI Builder is one such application that runs on the GI runtime. GI Builder consists of the files GI_Builder/, GI_Builder.* and shell.* from the GI installation directory.

When you deploy an application you copy the GI runtime and your application resources to a server. Your application runs on this copy of the GI runtime. If you copy the runtime from the GI installation directory then your application is running on the same runtime as is GI Builder when you run GI Builder on your computer.

There's no reason that GI Builder and your application have to run on the exact same runtime. In fact there are many reasons why you would want to have them running on different runtimes. For example, you probably want to run GI Builder on the "debug"
runtime so that you can see more warnings while you are developing your application. But when you deploy your application you want it to run on a runtime that is as small and fast as possible.

This article will show you how to compile the best runtime for your deployed application. This is the runtime that you will want to upload with your application when you deploy it on a public HTTP server.

Load Performance

Load performance in a web application running over HTTP comes down to a few simple principles:

  1. Load as little as possible
  2. Load what you need in as few HTTP requests as possible
  3. If requesting multiple resources, load them in parallel as much as possible

Recent versions of GI are good at loading runtime and application resources in parallel so you don't have to worry too much about the third point. Creating an optimized runtime build will take care of the first two points.

Sometimes points one and two conflict with each other. For example, part of your application might use jsx3.gui.Matrix but that part is not commonly used. Should you reduce the number of requests by merging jsx3.gui.Matrix with the set of required classes? Or should you load as little as possible up front and load Matrix as needed? There is some art as well as science to resolving these decisions. My usual suggestion is to merge all resources that must load for your application to reach its first interactive state, and nothing else.

Determining What Classes to Load

The GI runtime consists of a number of required classes (e.g. jsx3.lang.*, jsx3.app.*) and many optional classes (e.g. most of jsx3.gui.*). To create the optimal build for your application you need to determine which optional classes are used by your application. To do this, follow these steps:

  1. Make sure you are running Builder on either the source distribution of GI or the standard or debug packages. Running on the max build won't work for these instructions.
  2. Open your application in Builder running on Firefox with the Firebug extension installed, IE8 or Safari 4.
  3. Make sure that your logger.xml contains the following lines:
    <handler name="console" class="jsx3.util.Logger.ConsoleHandler"/>
    ...
    <logger name="bench.jsx3.lang.ClassLoader" level="TRACE"/>
  4. Launch your application from Builder
  5. Open your browser's JavaScript console for the window that contains your running application. You may have to reload your application after you open the console.
  6. Wait for your application to reach its first interactive state, such as the home page or login screen.

At this point you should see a bunch of log messages in the JavaScript console like

2010-04-27 14:18:11.778 bench.jsx3.lang.ClassLoader (INFO) - JSX/js/jsx3/gui/Button.js : js.eval : 10ms

These are the optional GI classes that your application is loading before it reaches its first interactive state. All of these classes should be included in the build of GI optimized for your application. Make a note of the full list of classes. We'll use this list in the next step.

Configuring and Running the Build

Make sure you are set up to make custom builds of GI as described in my earlier post. Create a new properties file in GIHOME/build and call it something like app1-build.properties. This file will contain the parameters for the build optimized for your "app1" application.

Into this properties file add the list of classes you saw in the JavaScript console. So if the entire list of classes was jsx3.gui.Button and jsx3.gui.CheckBox your properties file would like like:

build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox

Since you don't need to build Builder or the documentation you can add these lines to speed up the build.

build.gi.includes.jsx = default,jsx3.gui.Button,jsx3.gui.CheckBox

build.gi.docs = false
build.gi.docs.html = false
build.gi.ide = false

To create the build run the following commands.

$ cd GIHOME/build
$ ant clean; ant -propertyfile app1-build.properties

Once you have the build you should run your application on this build. To do this create a launch page with Builder and then hand edit it so that it points to the JSX30.js from your custom build. Make sure to copy the logger.xml file from your Builder installation to the new runtime.

This time when you run your application you should not see any logging messages with subject bench.jsx3.lang.ClassLoader. Repeat the steps in Determining What Classes to Load to make sure that all optional classes that your application uses are included in the optimized build. It may take your several iterations to finalize the list.

Once you have a fully optimized build simply deploy it along with your application to your web host. All the optional classes that your application uses will be baked into jsx.js, meaning that many fewer JavaScript resources must load when your application loads.

Congratulations, you have created an optimized runtime build for your GI application. Remember that every GI application has a unique load profile. You may want to create an optimized build for each of your applications or, if they are similar enough, create just one optimized build. The advantage of having just one build for multiple GI applications is that the runtime will be in the browser cache when the user visits the second and subsequent applications.

Additional Deployment Parameters Affecting Load Time

Here are a few more things you can do to speed up the loading of your application.

Don't load logger.xml

If you are not going to be monitoring the runtime logs of your application you can opt not to load logger.xml. It's just one small file but when your application is loading over HTTP every resource counts. Modify your launch page as follows.

<script src="gi/JSX/js/JSX30.js" jsx_logger_config=""></script>

Don't load messages.xml

The file messages.xml contains the English translations of all system error messages. If you do not load messages.xml you still see errors in the logs but instead of a nice English message you just see a string key. Again, it saves you just one file.

<script src="gi/JSX/js/JSX30.js" jsx_no_messages="true"></script>

Don't load locale.xml

The file locale.xml is required if you are using DateFormat, NumberFormat, DatePicker, TimePicker, Select or any of the Cacheable controls with XML Async = true. If you use none of these you can safely prevent locale.xml from being loaded.

<script src="gi/JSX/js/JSX30.js" jsx_no_locale="true"></script>
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.