Performance is important for all applications, some more than others. Below we’ve compiled a list of tips for improving the performance of your Ext JS or Sencha Touch app.
1. Avoid Ext.ComponentQuery.query
When finding a component in Ext JS, try to avoid Ext.ComponentQuery.query if you can. This is typically used to find components globally and there are a few alternatives that can help avoid this operation.
Using .up and .down functions from a target component is typically faster since it limits the area a query search will take place and it will return the first element it finds rather than searching for multiple.
// Searches parent components this.up('#myComponent'); // Searches child components this.down('#myComponent');
You can also query inside an element to avoid searching the global space.
// Searches for multiple child components container.query('#myComponent');
If you must use Ext.ComponentQuery.query, make sure you query for multiple components where you can. This is commonly forgotten about functionality.
var myComponent = Ext.ComponentQuery.query('#myComponent'); var yourComponent = Ext.ComponentQuery.query('#yourComponent'); // Querying for multiple components will find them in one pass rather than multiple var ourComponents = Ext.ComponentQuery.query('#myComponent, #yourComponent');
2. Batch creation of your views
It’s easy to use multiple calls to the add function without considering the performance implications. Below are some examples of slow and fast ways to use this functionality.
// Slow this.add(header); this.add(main); this.add(footer); // Adding multiple in the same call is faster this.add(header, main, footer); // Or as an array this.add([header, main, footer]);
It’s also possible to suspend layouts temporarily
// Also fast this.suspendLayouts(); this.add(header); this.add(main); this.add(footer); this.resumeLayouts(true);
3. Avoid unnecessary panels
Try to use the Container component wherever you can instead of Panel. Ext JS defaults to Panel, but Container is a much more lightweight component. Ensure you’re using Container in places that you don’t need the full functionality of the more powerful Panel Component by specifying the xtype.
4. Reduce component and store nesting
Think carefully when nesting components and ensure you don’t nest them deeper than you need to. This can be more expensive to render and harder code to follow overall.
Likewise over-using associations within stores can cause some serious performance decreases. Try to keep them as simple as possible and measure the performance impact with console.time
5. Proper handling of listeners
Improper usage of listeners can be a common cause of memory leaks and performance issues. Make sure that when you create a listener that it is being destroyed properly. The following type of listener attached to a component is destroyed automatically.
Ext.define('MyApp.view.main.MyList', { listeners: { itemtap: function() { console.log('item tapped!'); } } });
However, global listeners or listening to a different component must be removed manually. Best place for this is typically the components destroy method.
// Must be removed with Ext.un Ext.on('globalevent', this.myCallback, this); // Must be removed with component.un component.on('compevent', this.myCallback, this);
6. Avoid store.each for large data sets
.each
as well as the native .forEach
require a function to invoke for every item in the array. If you don’t require this functionality a simple for loop can be significantly faster.
// Slow var totalCost = 0; myStore.each(function (record) { totalCost += record.get('Cost'); }); // Fast var totalCost = 0; var records = myStore.getData().getRange(); for (var i = 0; i < records.length; i++) { totalCost += records[i].get('Cost'); }
7. Adjust CSS animate frame-rate
By default all CSS animations run at 60 frames per second(fps). This provides a smooth looking animation, but in a lot of cases this isn’t necessary. You may be able to gain some performance by reducing the fps of certain animations, and in a lot of cases gaining performance without much of a noticeable difference to the end user. This example illustrates how to change the steps of an animation, or the number of frames for the complete animation.
// 30fps for 1s, 15fps for 2s animations animation-timing-function: steps(30);
8. Careful use of getWidth and getHeight
Requesting certain information from DOM elements can cause the browser to recalculate style and layout. Doing this too often is commonly called layout thrashing. A detailed list of things that trigger this has been compiled over at GitHub. Probably the most common versions of this you’ll find in Ext JS are getWidth and getHeight. Call these as infrequent as possible by storing the returned value in a variable and try to do it before you make any other alterations to the view.
9. Ensure browser caching is enabled
When assets are served to the browser (js, png, jpg, css), headers should contain an expiry date to avoid each page change from downloading the same assets again. This is a simple thing that is commonly missed when configuring your server. Making sure common assets are set to at least 1 week can make page loads much faster.