High Performance PhoneGap Apps

How to Make High Performance PhoneGap Apps



·

I wasn’t fortunate enough to attend PhoneGap Day this year, so my experience of it was skulking around the #pgday hashtag on twitter and experiencing it through others who actually were there. There was certainly some interesting news to come out of the day, perhaps most notably Content Sync.

The most valuable talk I came across was by Syd Lawrence on Making High Performance PhoneGap Apps. You can check out the slides below:

I haven’t been able to track down the video for this presentation (if anyone has it, please do share!), and unfortunately the slides don’t contain much information (all good talks don’t have much information on slides as the focus should be on the talk, not the slides – but that doesn’t make things easy for those of us who missed out!).

So, until the video comes out I’ve taken the liberty to expand upon the slides a bit. I haven’t seen Syd’s talk either so I hope I don’t butcher his points!

UPDATE: The video is out!

It’s easy to write bad JavaScript

This is the point Syd opens with and it’s probably one of the main issues with HTML5 based mobile applications, and partly why they have a reputation of being less performant than native applications. It’s so easy to write a mobile application with JavaScript, and it’s also really easy to make a bad one.

When building mobile applications in JavaScript they need to be constructed carefully to ensure decent performance. The rest of Syd’s talk focused on 7 things you can do to make your HTML5 application feel just as good as a native application.

1. Use a JS Framework

This is the most important one. There’s teams of people who have put 1000’s of hours of work into creating JavaScript frameworks for creating HTML5 mobile application that make it easier and quicker for developers to create mobile applications AND they take into consideration a lot of the potential performance problems.

If you try to create a HTML5 mobile application without using a framework it’s either going to be really bad (in most cases), or you will spend a ridiculous amount of time creating something that could have been more easily achieved with the use of a framework.

I’ve written about why you need to use a HTML5 framework previously if you would like to see more of my thoughts on the matter.

2. Avoid “Janky” animations

As an Australian I had never actually heard of “Janky” until I had an American room mate who used it all the time. For those still uninitiated, “Janky” essentially means “weird, bad, wrong”. In this sense, janky refers to animations with CSS that are not smooth.

To avoid this, Syd suggests using CSS transitions in the following manner:

BAD:

.el {
     top: 0;
     transition: 200ms top;
}

.el .animated {
     top: 20px;
}

GOOD:

.el {
     top: 0;
     transition: 200ms transform;
}

.el .animated {
     transform: translate3d(0, 20px, 0);
}

In the bad example the position is being animated 20px from the top by transitioning the ‘top’ attribute. In the good example the same change is taking place but instead the position is transitioned using transform with translate3d.

You can read more about the reason for this here but the gist of it is that transitioning some properties (like top) cause the browser to recalculate styles every frame, which can be quite resource intensive and is more noticeable on mobile devices which have less power than a desktop computer.

By using CSS transformations, the rendering is offloaded to the GPU by essentially turning the element into an image during the transition which avoids style recalculations. By using translate3d, we set the transformations z axis which forces this use of the GPU. This isn’t necessarily a magic solutions and there are some issues to consider, again I’d recommend reading this article for more of a background.

3. The Dreaded Tap Delay

One of the biggest telltale signs that an app was built with HTML5 rather than native (which is not inherently a bad thing, be proud your apps are built with HTML5!) is the 300ms tap delay. Any time a user taps anything within your application, the browser powering the application will wait 300ms before actually firing the click event. This contributes greatly to the feeling of the app feeling a little off and slow, and not quite as nice as a native app.

I’ve written more about this issue, along with a tutorial you can follow to remove the 300ms tap delay in HTML5 mobile apps.

4. Offline Storage

Local storage is a really easy way to store data for an application. It uses storage allocated to the app within the browser which allows you to store simple strings and retrieve them later (and by using JSON strings we can also store more complex objects that we can decode later). There are issues with local storage though, one being the limited storage space available and there may also be some persistence issues with the data.

One good solution is to use an SQLite plugin which gives you access to native storage (removing the space restrictions). You can also use Pouch DB, which is an open source JavaScript database, in conjunction with the SQLite plugin. This provides a simple NoSQL style syntax which allows you to easily store and retrieve data AND it can even keep your local data synced with a remote database!

It’s pretty much as simple as running the following code in Pouch DB:

var localDB = new PouchDB("todos");
var remoteDB = new PouchDB("http://serverip:5984/todos");

localDB.sync(remoteDB, {live: true});

I’m yet to play around much with Pouch DB but you can definitely look forward to some posts in the future. Fortunately, Holly Schinsky already has a great tutorial on implementing PouchDB in an Ionic application.

5. Background Tasks

Syd mentions that updating the UI when the app is in background is bad – I’m not sure on the reason for this though so unless you happen to be reading Syd and want to comment I guess I’ll wait until the video is out!

6. Avoid memory leaks

When dealing with mobile devices we don’t have oodles of memory and power to work with, so it’s important to take steps to make sure we’re not using it unnecessarily. Syd had a few recommendations for this, but there wasn’t much to go on on the slides. So I’ll go off the headings from the slides and try to elaborate on what I think he was talking about.

Code reuse = element reuse

The DOM is one of the biggest culprits for decreasing performance of HTML5 mobile applications, despite a ton of advances being made in JavaScript performance DOM manipulation remains to be one of the biggest bottle necks of performance. It is therefore important to make the DOM as simple as possible and one way to do this is to reuse DOM elements. In good frameworks like Ionic and Sencha Touch for example, if a list has 100 items, only those on screen and a few more will be rendered in the DOM. Once a list element goes off screen the element is recycled and moved back to the top.

Reusing elements in this way could be quite complex and for the most part your framework should take care of it for you. The most important thing for you to do is to keep the DOM as small and simple as you can wherever you can.

Fully remove media from memory

In JavaScript a resource is marked for garbage collection when all references to the element have been removed. So for example if we had finished playing a video we should remove it from memory by running:

video.src = '';

Test, Evaluate and Debug

Of course to make sure your application is performing well, you should frequently be testing and debugging your application. The developer tools available through the browser are a great way for tracking down potential performance issues. For example in Chrome you can go to the Profiles tab to collect the JavaScript CPU profile, which will tell you were execution time is spent in your apps functions. You can then sort by the total time taken to see if there’s any potential optimisations you could make to the functions that take the longest to execute.

7. Use Cross Walk

The final tip was to use cross walk. The Cross Walk Project allows Android applications to use the Crosswalk Webview instead of the default System WebView. This means you will have a consistent WebView even when using different versions of Android and other benefits such as increased performance, WebRTC, Web Components and so on. You can add cross walk to a PhoneGap project with this plugin.

I’ll update this post when the video of the talk comes out, and if you have any more suggestions for increasing performance in PhoneGap applications please leave them in the comments!