Performance in Ext JS

As architects, we'll start a project with a lengthy list of requirements from the client that need to be implemented for them to be satisfied. There'll be explicit things such as "login feature" and "mobile friendly", but there are requirements that are not included in this list that nonetheless are unavoidable requirements for every client.

One of these is that the application should perform well. This is a catchall term that could include:

  • Responsiveness of UI elements
  • Initial application start up time
  • Remote requests such as load/save

A slow application is a key source of user frustration and the first step to diagnosing any issues of this nature is to collect information.

Let's look at the various ways in which Chrome Developer Tools can help us and address common problems using Ext JS.

Network performance

As we've seen in our examples, many Ext JS applications will communicate with a backend API service in order to read and write data. If user feedback shows that remote requests are unresponsive, we need to first diagnose the calls that are causing problems. Chrome can help us here.

With the Developer Tools open, click on the Network tab and refresh the page. We get a list of all of the resources requested as the application loads; we can filter this by clicking on one of the headers at the top of the pane. Here's the Alcohology application filtered to "XHR" or Ajax requests:

Network performance

Chrome Developer Tools with an Ajax request selected

In this example, one of the requests has been selected and a breakdown of timing details in shown on the right-hand side. While the Alcohology application has a very fast response time, it serves as a good illustration of how to analyze network performance.

Note

More details about the Network panel can be found at https://developer.chrome.com/devtools/docs/network.

How does this help us? If the remote server is slow, then as frontend developers, there's not much we can do about this; other than keeping our remote requests to a minimum, we're stuck with what's available. Here's one example that we can act on in order to speed things up.

Note the "stalled" entry in the timings. This is often caused due to the limit that browsers impose on the number of connections that can be active to one origin (such as a domain or subdomain) at a time. When this number is exceeded, the browser will block any new requests until a connection becomes available. This knowledge gives us several opportunities for optimization.

Make fewer requests

The no-brainer approach to this problem is to simply request fewer things from the server and Ext JS gives us several ways to do this. First up is a technique we used in the Alcohology app (use an icon font such as FontAwesome instead of image icons). This means that we'll only have to download one font file rather than multiple icon files. The glyph config on menu items and buttons gives us a really easy way to use this feature and negate the need to use bitmap images for icons.

Next up is nested data. This is an approach that we used in the Questionnaire component, but one that needs to be used carefully. By setting up model associations, we can request data for the whole hierarchy and populate our data model all at once, rather than per mode type.

For example, for the Questionnaire component, we could have loaded the questionnaire, the steps, and the questions in three separate requests, but by bringing it all down at once, we avoided the two remote requests. There are two caveats to this idea; firstly, the server needs to support nested data; secondly, the size of the nested data maybe much larger and therefore result in a slower response time. Multiple separate requests might result in better perceived performance, so application of this concept strongly depends on the situation, speaking of the perception of performance, and so on.

Perceived performance

There are some cases in which we can't improve the load time of certain aspects of an application, for example, it could be report generation where the number crunching involved is a long-running operation.

In these cases, we need to do what we can to improve the user's perception of performance and assure them that the action they're undertaking is underway and will finish soon.

In Ext JS, one key mechanism to do this is Ext.LoadMask. It's used by Ext JS internally in several situations:

Perceived performance

In the previous example from the Ext JS Kitchen Sink, a grid with a paging toolbar will automatically use LoadMask while waiting for the server to return the next page.

The advantage to the user is that while they have to wait, they're at least being told that they have to wait. Without LoadMask, they'd have hit a button and received no feedback that the server was thinking about the request.

We can leverage LoadMask in our own code by creating a new instance when we need it, but it's more likely that we'd use it on an existing container and leverage the fact that many Ext JS components have LoadMask functionality baked in.

We can use event domains, which we discussed back in Chapter 2, MVC and MVVM, as one way of hooking into remote requests and masking our components:

listen: {
    store: {
        'products': {
            'beforeload': function() {
                this.lookupReference('list').mask('Loading...'),
            },
            'load': function() {
                this.lookupReference('list').mask(false);
            }
        }
    }
}

In this code snippet that we added to the ProductController on Alcohology, we tell the listen config to watch out for beforeload and load events on the products store. The listener can use the "products" alias that we'd already set up on the products store class. When the beforeload event fires, we grab the product list view and call its mask method to show its LoadMask. When the server response returns and the load event fires, we call the mask method with the false argument to hide it again.

It's a simple and an unobtrusive way to wire up the loading mechanism and give the user that all-important feedback, showing that their actions have triggered an effect.

Load less

One very simple way to speed up the response of Ajax requests is to simply request less stuff! If the server supports paging, then any component powered by a store can immediately become more performant by requesting a single page of data rather than pulling it down all at once.

Ext.PagingToolbar can be linked to a store and placed anywhere in an application to provide a pagination UI:

bbar: [{
        xtype: 'pagingtoolbar',
        store: { bind: '{products}' },
        displayInfo: true
}]

Here, for example, is how we'd begin to add a paging toolbar to the Alcohology application's product list view. It automatically takes on touch-friendly styling from the theme we used:

Load less

Alcohology's product list complete with paging toolbar

A more advanced version of this technique involves using the Ext.data.reader.Reader.metaData property or the Ext.data.proxy.Proxy.metachange event. This can be used to pass data from the server to the client, which is in turn used to configure the Ext JS application; a common example is to allow the server to specify the columns that a grid contains when it first loads.

This could mean that on initial load, the server omits a field and matching grid column, such as a description, which may contain a lot of data. The user could customize the grid via the column header UI to show it when they need it.

Optimistic updating

When saving a record to the server, we'd normally see the following actions:

  • User clicks a button to save the record
  • Ext JS displays a "saving" message
  • Save completes and a "success" message is displayed

In some situations though, we can trust that the server is going to save successfully and cut the actions down to the following:

  • User clicks on a button to save the record
  • Save proceeds and a "saved" message is displayed

In this case, the save action happens entirely in the background and doesn't block the user from performing other actions. You can see this kind of behavior in many e-mail applications with the server interaction happening behind the scenes and an "outbox" to store messages that fail to send on the first try.

In the event that the server does raise some kind of error, we can display a failure message and rollback the changes that the user performed. The Ext JS grid includes UI to do this; it will highlight changed values with a red marker that can be cleared when we're sure the record has been successfully committed to the server.

This is an advanced technique that requires extra UI design work, but it can immeasurably improve your user experience.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset