Is jQuery Too Big For Mobile?
The modern web is always changing, and this article is more than two years old.
By TJ Van Toll
This question gets asked a lot, and I’ve yet to see a data-based exploration of this topic. Terms like “big” and “bloated” are relative terms; they don’t mean anything without numbers to back them up. The real question should be – “Does the size of jQuery adversely affect the users of my applications enough to outweigh the development conveniences that the library provides?”
To answer that question, we need to determine how long it takes to load jQuery on mobile devices. The rest of this article is dedicated to determining that number, and to get it, we have to start with a discussion of how the
<script> tag works.
The <script> Tag
We’ve seen this code countless times, but what does the browser actually do when it parses this line of HTML? The answer is: a lot – but we can break it down into two high level tasks:
- Retrieving the file (either from a cache on disk or from the network).
- Parsing and executing the script.
Let’s explore each of these individually.
For the purposes of this article, we’ll assume a worst-case scenario: a user visiting an application for the first time with no cached resources. When the browser doesn’t have the script cached, it has to turn to the network to get the file it needs. To measure how long this download will take, there are two factors we need to be concerned with: bandwidth and latency.
Bandwidth refers to the speed at which the browser can download a resource from a server, and is most commonly measured in Mbps (megabits per second).
In 2012, the average download speed of mobile networks worldwide varied from ~2 Mbps in some Asian countries to ~1 Mbps in Russia and India. That data is slightly dated, and newer networks advertise faster speeds, for example
- Virgin Mobile claims its 4G network has download speeds that vary from 3 Mbps to 6 Mbps.
- Verizon Wireless claims its 4G network has download speeds that vary from 5 Mbps to 12 Mbps.
- LTE networks offer speeds that average from 6.5 Mbps in the US to 24.5 Mbps in Australia (data is from Q1 2014).
Since this article is about jQuery, let’s use these numbers to determine how long a download of jQuery takes. We’ll base all numbers off the minified version of jQuery 2.1.0, which is 28.65KB gzipped (and only the gzip size matters here because it’s the only thing sent across the network).
A network with download speeds of 1Mbps can download 125KB in a second, which means that for every 1 Mbps your mobile network provides, you can download 4.36 jQuery’s/second. Or to put this in terms of time, it means that jQuery takes
- 229ms to download on the worst mobile networks (1Mbps),
- 46ms to download on average mobile networks (5Mbps),
- 19ms to download on awesome mobile networks (12Mbps).
We’ll return to these times later, but at a glance these numbers aren’t that concerning. In fact, from a more general perspective, bandwidth is very rarely a bottleneck for mobile web performance. For instance, Ilya Grigorik from Google found that upgrading from a 5Mbps network to a 10Mbps one improves page load times by a mere 5%.
So if bandwidth isn’t a bottleneck, what is?
In the context of web applications, latency is the amount of time it takes for the browser to connect with an external server on the network. Latency is typically measured in RTT, or Round Trip Time – which is the amount of time it takes to make a round trip from the browser to an external server.
Historically, we didn’t worry too much about latency for desktop development, as RTTs on wifi networks are small – typically well under 50ms.
We have no such luck with mobile. In 2012 the average RTT time on a mobile network in the United States was 344ms. And that 344ms applies to not only every HTTP request – which the average web page now makes 93 of – but also every DNS lookup and TCP connection.
The RTT data is from 2012, and average RTTs have improved some. For example Virgin Mobile advertises that the average latency on its 4G network is now 150ms. But while average RTTs are improving, there are only small additional gains to be had, as current networks are within a small factor of the theoretical limit dictated by physics.
But there’s a silver lining to all of this. Remember that we’re talking about jQuery, and there’s a simple way to avoid any additional latency costs when using jQuery: instead of placing jQuery and your app’s code in their own files, concatenate them and serve them together.
<!-- Before --> <script src="jquery.js"></script> <script src="app.js"></script> <!-- After --> <script src="app.js"></script>
This simple change removes a RTT needed to load jQuery in your application. This same guideline applies to loading jQuery from an external CDN. Because of the fragmentation in CDN providers, jQuery versions, and protocol usage (http vs. https), the chances of getting a CDN cache hit are shockingly low – and downloading from an external domain has the potential to perform not one, but three round trips (a DNS lookup, a TCP connection, and an HTTP GET).
Parsing and Executing the Script
After the browser has downloaded the textual content of jQuery, it has to turn that text into bytecode and execute it. Under the hood, this is a complex process that is well beyond the scope of this article, but since we’re only interested in the time this whole process takes, we can measure that without getting into the messy details.
I devised the following test to measure how long the parsing and execution of jQuery takes.
<script>var start = new Date();</script> <script> /* jQuery's minified source code in its entirety */ </script> <script>alert( new Date() - start );</script>
I experimented with
console.timeEnd(), but did not use them because they’re unsupported in older mobile browsers. In supporting browsers I received nearly identical times using
console.time()as I did with new
To isolate the parsing and execution time, I take the network out of the equation by including jQuery in an inline script (hat tip to Eric Lawrence for the suggestion). The results of running this test on a series of browsers is shown below.
|Browser||OS||Time to parse/execute jQuery 2.1.0 (in ms)|
|IE 11||Windows 8.1||18, 21, 14, 16, 15|
|Chrome 33||OS X 10.9.2||15, 8, 5, 7, 6|
|Safari 7||OS X 10.9.2||9, 5, 3, 3, 2|
|Firefox 27||OS X 10.9.2||12, 12, 11, 12, 12|
|Safari||iOS 7||178, 125, 44, 87, 96|
|Default Android||Android 2.2||1184, 268, 299, 216, 422|
|Default Android||Android 4.0||603, 465, 106, 145, 243|
|Chrome 33||Android 4.4||219, 86, 38, 86, 123|
|Firefox 27||Android 4.4||269, 367, 400, 381, 264|
The desktop browser tests were run on a high-end MacBook Pro, and the mobile tests were performed on devices that I own. I did not clear the cache between runs; I simply hit the browser’s refresh button. This did produce an interesting result: the WebKit-based browsers appear to cache results of some portion of the parse phase, whereas Trident and Gecko do not. If any engineers from these rendering engines read this, I’d be interested in the details. I’d also love suggestions on more robust ways of obtaining these times.
All desktop browsers – IE, Chrome, Safari, and Firefox – handled this task with ease. Even the worst of the four was able to parse/execute jQuery in an average of 17ms.
Mobile, however, is a different story. Whereas Mobile Safari on iOS7 and the latest Chrome for Android handle this task decently, older Android is a completely different story. My first run of this test on my Android 2.2 device took over a full second. And although I didn’t have any feature phones handy to test on, I fear they would do even worse.
There is one piece of good news in this data: Moore’s law is clearly at play here; you can see the Android times improve as versions roll out, and there’s no reason to believe that this trend won’t continue into the future.
So is jQuery Too Big?
We’ve gone through all of the data, so now it’s time to return to the question. And like the answer to any software development question, the answer always depends on the specific situation. Let’s start by summarizing our numbers.
- Downloading jQuery 2.1.0, or 28.56KB takes
- 229ms to download on the worst mobile networks (1Mbps).
- 46ms to download on average mobile networks (5Mbps).
- 19ms to download on awesome mobile networks (12Mbps).
- Downloading jQuery adds zero latency as long as you’re concatenating it with you app’s other scripts. If you’re not, expect an additional script to add roughly 150ms to 1 full second of load time to your application.
- Parsing/executing jQuery 2.1.0 takes
- ~15-20ms on desktop browsers
- a few hundred milliseconds on most mobile browsers
- possibly a full second or more on old devices.
The numbers that stand out the most are the parse times on older Android browsers. Having the potential to add a full second or more of load time to your application is a really bad thing.
But let’s get back to the numbers. Per the data above, a typical user on an average device and network will take ~50ms to download jQuery and another ~250ms to parse it. To equate this to money, Amazon famously found that every 100ms of delay in the load time of amazon.com cost them 1% in sales. If we accept this finding verbatim, it would mean that including jQuery decreases your mobile sales by 3%. That sounds bad, but you have consider the flip side as well; if using jQuery improves your productivity enough to generate 3% more revenue, in theory including it is worth the trade off.
Another thing to keep in mind is that jQuery 2.1.0 is comprised of AMD modules internally; therefore if you’re concerned about these load times, it’s easy to reduce them by building a custom jQuery containing only the parts you need. But before you go down that route, there’s one final thing we need to touch on.
There’s Almost Certainly Something Way More Important to the Efficiency of Your Application Than Whether You Use jQuery
According to the HTTP archive the average Web page now
- is over 1.7MB,
- makes over 90 HTTP requests,
- includes over 1MB of images,
- makes only 46% of its resources cacheable.
So before you care about jQuery, first make sure you
- minify your CSS/JS assets,
- concatenate your CSS/JS assets,
- gzip your HTML/CSS/JS assets,
- compress your images,
- set appropriate cache headers,
- remove unnecessary HTTP requests.
Often removing an image or two can improve your performance more than removing jQuery, and is far easier to do. If you have performed all these optimizations, and are still experiencing performance issues on mobile devices, then look into removing libraries like jQuery – just make sure you cover your bases first.