Effect of jQuery and jQuery Mobile on PhoneGap/Cordova Startup Speed

App load time can have a significant effect on how users perceive your app (see these articles). While load time of Cordova apps is a complex thing made up of multiple steps, one (possibly big) part of it is loading all the JavaScript and CSS resources on the initial HTML page.

An often used framework for mobile apps is jQuery Mobile. Just look at the "related tags" statistics on Cordova questions on StackOverflow. Such libraries are useful for beginners. Lately, though, I have been trying to write plain JavaScript without libraries. To validate the performance gains from this approach, I wanted to see how much using jQuery and jQuery Mobile affect the load time of an app.

Measurements

I originally measured with four devices: iPhone 3GS, iPhone 4S, iPad 2, and 3rd generation iPad. While I procrastinated writing this post, new devices were released (and bought). So I made additional measurements on iPhone 5S and retina iPad Mini as well.

In all measurements, I used Cordova 3.0 (although 3.1 3.2 3.3 is already released). I had the console plugin installed, but no other plugins. The template I used was a stripped down version of the default project template (see this gist for the complete HTML I used). I had three versions:

  • without any JavaScript libraries, only loading cordova.js
  • with cordova.js and jQuery 2.0.3
  • with cordova.js, jQuery 1.9.1, and jQuery Mobile 1.3.2 (including CSS and JavaScript)

The versions of jQuery and jQuery Mobile are the latest versions at the time of making the first measurements.

I measured the time between a script element in the beginning of head and the deviceready event to fire (as you can see from the template). With each device, I measured every version 10 times to get more reliable data.

Results

The results are summarised in the figure below. The raw data is also available.

measurements.png

The results show no real difference between iOS 5 and 7 on iPad 2 and between iOS 6 and 7 on 3rd generation iPad. Neither is there much difference between those two devices. iPhone performance has clearly improved in newer devices. The same is true for iPad Mini. Nothing surprising in that, though.

What is notable is that jQuery Mobile does affect the start-up time of the application quite significantly. In most devices, it takes around 0.5s for the deviceready event to trigger. And over 0.4s even on the latest iPhone, not to mention the over a second on 3GS.

Take Aways

So what can we learn from the results? I’d say that if you target older versions of iOS which run on 3GS (or, perhaps iPad 1), you should think long and hard before you adopt a large library like jQuery Mobile. If you still device to go with jQuery Mobile (or similar libraries), the load speed of the app could (and should) be improved by loading the libraries after deviceready. Also, I used the complete library, and you should definitely build your custom version with only the needed components.

Another alternative is to use more lightweight frameworks such as Zepto + Topcoat. The fastest approach, performance wise, is writing JavaScript and CSS without libraries. If you are not comfortable with that, now might be a good time to learn.

All in all, just keep in mind that half a second can feel like a long time and can have an effect on your app ratings and business performance. On the other hand, if you do a lot of other processing on startup, the JavaScript loading times might not be a significant factor in app startup.

Conclusion

As with most questions in software development, my suggestion whether or not to use libraries in Cordova apps is “it depends”. It is a balance between app load performance and developer productivity. Just keep in mind that the libraries you use can have a big impact on load times. Personally, while I do have an app in the app store (published by my previous company) that uses jQuery Mobile, I would not use it in a new project.

What do you think? Do you use libraries in your Cordova apps?

Update: If you read this far, you might also want to check out the post about whether you should minify your resources in a Cordova/PhoneGap app.


Want to get more posts like this to your inbox?

Sign up for my newsletter to get an email on new posts like this. I don't email you too often, only when I have a new interesting post to share with you.

5 App Reviews

“Rate the App” dialogs have gained a lot of attention in the developer community lately. I don’t want to do what John Gruber did not suggest: rate an app showing a review prompt with 1-star. I find Rene Ritchie’s idea of rating 5 favourite apps right now much more constructive. So, I rated my favourites: 1Password, Mr. Reader, Runmeter, OmniFocus, and ReittiGPS.

I rated Runmeter “only" 4-stars because of the most annoying rating dialogs it shows.

Safari on iOS 7

Last week, iOS 7 was released and, again, the speed of adoption has been amazing. Maximiliano Firtman has a great post summarising the changes in Safari in iOS 7. A lot has changed, not all for the better as he says: "this is the buggiest Safari version since 1.0".

To me, the interesting new features include:

  • video <track> support for subtitles and closed captions
  • <progress> element support for creating progress bars
  • Airplay API for streaming content to other devices
  • paginate mode to enable easy pagination of pages in a UIWebView

There are some not-so-good news as well:

  • Nitro JavaScript engine is still not used in UIWebView
  • Support for input type datetime has been removed

The last point required me to update my app, since form fields using the type datetime are now rendered as text fields.

There are plenty more interesting details, so I suggest you read the whole post.

PhoneGap Files, Filepaths, Backups, and a Nasty Bug

I recently updated my main phone to iOS7. To my surprise, images within my The Fisher app no longer appeared. All the stored data was there but instead of the images I only got a white screen.

My first hope was that this was due to my app not being the version downloaded from the App Store and the restoring from backup not working for non-App Store. But I had to test it with my backup phone which I can easily erase and restore from backups. After testing, I was in a bit of a panic mode since the images really were not restored from the backups. To put it mildly, in an app with user-generated content, losing that content is not good.

Inspecting the contents of the app bundle with iExplorer (which I highly recommend), I found out that the files were there but they were not shown in the UI. Comparing the catches from the backup with newly added catches, I noticed that the file paths were different.

PhoneGap Files and Filepaths

On iOS (and when working with PhoneGap), files have a path like this:

file://localhost/var/mobile/Applications/C5875140-A4D2-4310-A6A7-55CC2F504F2A/Documents/1377869303030.jpg

In my app, I was saving these absolute paths to the database. And apparently you should never do that! As the Apple File System Programming Guide says, file paths consist of application home directory and the location of the file within the apps sandbox. The thing is, the application home directory can change at least when restoring from backups.

Fixing is Easy

Fixing the problem is easy. Instead of storing the absolute path of the file, you should only store the part of the file that you specify. In my app, the file names are based on the time they were created, so they are all of the form 1377869303030.jpg (or, [0-9]+\.jpg). Thus, whenever wanting to access the file, I can simply replace the beginning of the stored file path with the correct path to the application persistent file directory. To get this directory path, I have the following code executed on deviceready event.

function setFsRoot(callback) {
  window.requestFileSystem(LocalFileSystem.PERSISTENT,
                           0,
                           gotFS,
                           fail);
  function fail() {
    // handle the error
  }

  function gotFS(fileSystem) {
    // save the file system for later access
    window.FS_ROOT = fileSystem.root.fullPath;
    callback();
  }
}

A file path is then window.FS_ROOT + fileName. Changing all file access to work like this I was able to fix the issue with relatively little changes. If you are storing absolute paths, you should make this fix now, before everyone upgrades to iOS7.

Conclusion

Accessing files is critical in my app, so I really should have done a better job in testing backup restores. However, I do think that the Apple documentation as well as PhoneGap API docs should mention this potential pitfall.

Now my problem is fixed and an updated version 1.1.1 is already available in the App Store. Hopefully, no major harm was done to my users. I was also lucky that file removals used the same file path, so the user was not able to remove the catches before I updated the app.

App Transfers in Apple App Store

Last night I (like all iOS developers) got the email below from Apple. The gist of the mail is that developers can now transfer approved apps to other accounts. Previously this has been impossible to do. This has many benefits and use cases for developers:

  • If you sell an app, you can transfer it to the buyer instead of having to handle updates for them. Likewise, if you buy an app, you get full control to it in iTunesConnect under your own account.
  • If you outsource app development, the final deliverable can be an App Store accepted app transfered to your account without having to give your credentials to the developer or managing the App Store submission yourself.  Similarly if you develop apps for others.
  • If you develop apps on your personal account (like I currently do), you can start a company once things grow, without having to distribute the apps forever under your personal account. 

App transfers are also likely to boost the business of app marketplaces such as Apptopia .

introducing-app-transfers.png

The Fisher is in the App Store!

Last night, The Fisher was accepted to the Apple App Store! Again (more on that in a later post). For the features of the app, see the app page. Or just go and buy it :) Below are a few screenshots of the app.

Photoshoot for App Icon and Splash Screen

Back in November, I started really thinking about the icon and splash screen of The Fisher. My early idea was to find a freelance illustrator to design illustrations for both. As the whole idea of the app crystallized -- focus on pictures of the catches instead of the details -- it became obvious that both the icon and splash screen needed to be photographs. As I'm somewhat of a hobbyist photographer, I thought I could take the photos myself.

The Fisher app icon.

The Fisher app icon.

So one fine Saturday, I took the bus to the Hakaniemi market hall to buy a fish. The plan was to buy a big perch since that is my favorite fish; they are fierce fighters and taste delicious. I guess it was a good day for perch since they didn't have any for sale. Instead, I bought one pike-perch (aka zander). At 23 euros, it wasn't cheap. Besides the fish, I bought some smoked slices of ham and baloney. Both delicious :D

Anyway, back to the fish. Once I came home, I immediately started a photoshoot with my "catch". After all, the light hours in Finland in the winter are pretty scarce. The equipment and my setup was quite simple with only my camera on a tripod and the fish on the table. I took around a hundred photos of the fish from different angles and distances. While doing so, I realized why the zander isn't the most photogenic a catch: by nature, it keeps its mouth shut. To overcome this and to make it look more fierce, I had to put a toothpick inside its mouth to keep it open :)

With 100 photos, getting to the editing took some time and I only got to it yesterday, over three months after taking the photos. Now the app is close enough to v1.0 to concentrate on the icon and splash screen. I tried many of the pictures both for the icon and the splash screen. In this process, the Photoshop script by Josh Jones saved me a ton of time by allowing easy creation of the icon in different sizes. As for the splash screen, those I made by hand. The final splash screen image is on the right, the icon on the top of the post.

The Fisher splash screen.

The Fisher splash screen.

I'm not completely satisfied with either photo, but I do think they are different from the typical illustrations on App Store icons. The resolution of the icon is good nowadays. That makes me wonder what potential problems I'm missing, since most apps do use illustrations. By using a photo as the icon, The Fisher will be different from most of the apps it competes with. These are the icon and splash screen I'm going to ship version 1.0 with, but you can be sure I'll go and catch (or -- while there's still ice in Finland -- buy) other fish to update both photos for future version.

To summarize: For a few euros, I got the photos I needed, plus a delicious dinner (I cooked the fish in cream with pepper and horseradish). I'm close enough to submitting the app to focus on the icon, so it shouldn't be too long until I submit The Fisher to the App Store.