Speeding up initial page view of Ajax applications with static HTML

Many Ajax applications build the UI programmatically, i.e. think of GWT’s UI builder or one of the many convenient jquery widgets which incurs a visible delay between the time of the initial page load and the time the page has finished rendering. The delay can be mitigated by a static “please wait while loading” message embedded as a div into the page HTML which is removed after the javascript has loaded.

A more elegant approach, where feasible, is to serve the initial page with all the HTML required to render the first page, notably shortening the time until the page is visible to the user while the main javascript loads in the background. The code can then get elements from the DOM and wrap widgets around it, i.e.

Button.wrap(DOM.getElementById(...))

Personally I think that this approach is also more intuitive because HTML is after all the ideal markup language for web UIs.

A problem that arises from this approach is when your application has enabled history support. For example, a real-estate application that shows details for a house would construct a URL such as http://en.bazarooma.com/#451 in order to display the detail page for entry 451. Ideally, when directly typed into the address bar, the browser would show the page without first going through the initial page but in the approach I just described that is exactly what would happen:

1. Initial page is loaded with the first form’s HTML
2. javascript is loaded
3. javascript activates history handling, clears current page and shows new form

What the user sees is a brief (or not so brief) flash of the first page until javascript is loaded, and only then is the intended form displayed.

The solution is an extension over the principle:

1. The initial HTML contains markup for all forms

<div id="MainPage">.... </div>
<div id="DetailsPage">...</div>

2. All forms are per default invisible (via CSS)

#MainPage, #DetailsPage{
     display:none
}

.MainPage #MainPage{
     display: block;
}

.DetailsPage #DetailsPage{
     display: block;
}

3. An inline snippet of javascript (which is executed long before the bulk of GWT/jquery et al javascript is loaded) parses the URL, extracts the hash part and modifies the CSS so that only the correct form is visible

if ((window.location.hash+"").match(/^MainPage/)){
    document.body.className="MainPage";
}
if ((window.location.hash+"").match(/^DetailsPage/)){
    document.body.className="DetailsPage";
}
This approach is guaranteed to work even before any form HTML has finished loading from the server, because form visibility is defined by a class on the body element which is already in the DOM.

[update 04.04.2012] There are some pitfalls though: This technique works fine for all widgets that provide a wrap(element) method with a prominent exception being the Hyperlink class – I had to copy & paste one and extend it accordingly. Also note that when using composite widgets (think of panels containing other widgets) you have to first wrap children and then the parent container, otherwise RootPanel will throw an exception about the widget’s parent belonging already to the widget hierarchy. There is also a problem with HtmlUnit regarding links and history handling I’m discussing in this post [1].

We implemented this technique at Bazarooma so feel free to test it out and get a feeling of how it works.

Resources

[1] Missing history update when clicking on links in GWT and HtmlUnit unittests
https://blog.georgovassilis.com/2012/04/04/missing-history-update-when-clicking-on-links-in-gwt-and-htmlunit-unittests/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.