jQuery Mobile has just hit its beta 1 milestone, and there is much rejoicing. But having worked with the framework for a little while now, I’m having serious doubts about its suitability for mobile web applications at all. This isn’t a “jQuery Mobile considered harmful” piece; I just want to explain my own concerns.
The way I see it, the jQuery Mobile framework consists of four sub-frameworks:
- jQuery. jQuery Mobile is not a standalone library; it requires the jQuery core library.
- A CSS framework for styling elements to look like iOS-ish native controls
- A widget framework that automatically builds the (complex) HTML required by the CSS framework from (simple) declarative HTML.
- A client-side page navigation framework
Combining the CSS and widget frameworks allows you to write simple declarative code like this:
<a href="somepage.html" data-role="button">Button</a>
which gets turned into this:
<a href="somepage.html" data-role="button" data-theme="c"
class="ui-btn ui-btn-corner-all ui-shadow ui-btn-down-c ui-btn-up-c">
<span class="ui-btn-inner ui-btn-corner-all">
<span class="ui-btn-text">Button</span>
</span>
</a>
and is rendered like this:
The widget framework also allows you to create page and dialog widgets, that act as isolated screens within your application: only one is visible at a time.
<div data-role="page" id="index">
<div data-role="header">Home</div>
<div data-role="content">
<a href="#monkey" data-role="button">Monkey</a>
</div>
</div>
<div data-role="dialog" id="monkey">
<div data-role="header">Your monkey</div>
<div data-role="content">
<img src="http://example.com/monkey.png" />
</div>
</div>
These page widgets can be declared inline in your code (as shown above), built dynamically with JavaScript, or loaded from a remote server or from the local file system with Ajax. The page navigation framework takes care of hooking up the pages and dialogs, so that when you click on the “Monkey” button, the home page is hidden, and the monkey dialog is displayed. Very importantly, the framework takes care of browser history while navigating from page to page, so that the native back button works correctly. (Still buggy in beta 1, but I’m sure they’ll fix it.) It can also provide pretty animations for transitioning between pages.
Problem 1: “native” UI
If you’re happy sticking with the visual style of the framework, that’s fine. The jQM team has put a lot of work into making the UI components look very slick (and iOS-ish), and compatible across a wide range of browsers. But should a web application’s greatest aspiration be to look as much like a native app as possible? No. Remember building web apps to look like native Windows XP applications? Those were the bad old days.
The basic theme includes five colour swatches that you can apply and extend. But adapting the existing controls beyond just their colours and icons is more difficult precisely because they are generated from declarative markup, and the widgets only grant you limited options for tweaking their output. Of course, you are always free to bypass the widget system altogether and write your own markup using and CSS, and mix in classes from the CSS framework when appropriate.
Problem 2: Ajax navigation
Despite how easy Mark Pilgim makes it look, implementing a framework that gives you all the benefits of Ajax partial page loading, while at the same time maintaining fully linkable URLs is non-trivial. jQuery Mobile hasn’t tackled this yet. As you navigate between pages, you end up with hash-based, JavaScript-dependent navigation, which is bad.
So why do this in the first place? Why not just put each page on a separate URL, in the traditional web style, and ditch the client-side navigation altogether? Would jQM not work just as well as a CSS + widgets framework?
I don’t think so, because of speed — or rather, the lack of it.
Problem 3: size and speed
jQuery Mobile is not a stand-alone library; it is built on top of jQuery. Even though jQuery’s headline size may appear small (31.2KB minified and gzipped), and jQM doesn’t appear to add much on top of that (20.3KB minified and gzipped), this is not an insignificant amount of code for a mobile browser. Even if a browser already has these JS files available in its local cache, it still has to parse them on each new page load. And the painful reality is that mobile browsers are still really slow compared to their desktop cousins.
I’ve made a very simple test page to show how long it takes to just load (from cache) and parse jQuery (v1.6.1). Here are the very unscientific results from the devices I have to hand:
Device + browser | Time to load (from cache) & parse |
---|---|
iPhone 3G + Mobile safari (iOS 4.2.1) | 0.95s |
Samsung Galaxy Ace (Android 2.2.1) + Android Browser | 0.75s |
iPad + Mobile safari (iOS 4.3.3) | 0.29s |
Samsung Galaxy Ace (Android 2.2.1) + Opera Mobile 11 | 0.29s |
LG Optimus 7 (WP7, 7.0.7392) + IE | 0.27s (very pleasant surprise!) |
On other devices, performance can be even worse. 8 seconds on an older Blackberry? Try the page on your own phone and let me know how it shapes up. By comparison, on my laptop it takes about 0.02s to load & parse in Chrome 12, and about 0.05s in Firefox 5. So at a glance, it looks to me like mobile browsers are at least 5 times slower than desktop browsers.
When you’re talking about a consciously perceptible amount of time spent parsing a library, you’ve got a problem. Remember that this is just jQuery on its own, before adding in the jQuery Mobile framework and your own code, and before the browser has to do any actual rendering work to display your content.
Conclusions
The fact that jQuery Mobile sits on top of jQuery makes it a comfortable and attractive solution. If you already know jQuery, you’ll pick it up easily, and you’ll have all the power of jQuery available to you right off the bat. It’s well tested, and highly compatible. It’s under constant development, bugs get fixed all the time, and it has good community support. It’s better code than most of us are likely to write ourselves.
But the challenges of the mobile web are not the same as those of the desktop web. I have massive respect for everyone who works on them, but jQuery and jQuery Mobile do not address these problems adequately — yet. Performance is much more important, and much harder to come by because of slow devices and high network latency. Size matters a lot. When even big desktop web sites typically only exercise a small part of the code in jQuery core, you have to wonder if a mobile site is going to need all of it.
In summary:
- jQuery, and by extension also jQuery Mobile, is too big a library for a mobile site that uses standard URL-based navigation.
- Until the jQuery Mobile client-side navigation framework supports the HTML5 history API (pushState/popState), it will deliver problematic URLs. It’s up to you to decide whether this is a deal-breaker for your project.
- If you’re building a PhoneGap application, jQuery Mobile is perfect. As you load the app, you load the framework once, and then navigate between a set of predefined pages using Ajax navigation and smooth transitions. You don’t have to worry about hash-based URLs, because they are not exposed to the user, and you’re not expected to link to them. The native look of the controls matches the user’s expectations for a native app. Awesome.
- If you’re building a one-off mobile web application that you don’t expect to be around forever. jQuery Mobile might not not be the perfect solution for mobile web sites, but depending on the timescales and requirements of your project, it may very well be good enough.
- If you’re building a full-scale mobile web site or application that is going to be core to your business, you can use jQuery Mobile to get you to v1.0 quickly, but consider it a set of training wheels that you should shed after this point. Its limitations will constrain the changes and optimizations you can make in the future. The UI is not designed with your site in mind, and the underlying framework is bigger than you will need. (A big framework may lead you to be less critical of the size of your own code.)
I couldn’t agree more. As far as I can see, the only cross-browser JS framework which can be really usable now for general purpose mobile web sites is xui.js, but even this should be chosen with a grain of salt (e.g.: is a recent WebKit based engine to be assumed? If so, there may well already be some better choices).
jQuery Mobile is a terrific piece of code, and so is its base jQuery too – but we are getting too used to very high-level abstractions built on top of high level languages and APIs: this is simply not working properly on low power devices.
I get 1.33 seconds on the first page load and 0.612 on the cached page. This is with the HTC HD2, running a custom build of android.