Daniel shared a few examples in his deck, but I couldn’t wait to take Daniel’s tool and fire it up on a bunch of random browsers and devices that I have sitting around.
For this test, I decided to profile just jQuery 2.1.1, which weighs in at 88kb when minimized. jQuery was selected for its popularity, not because it’s the worst offender. There are many libraries much worse (hey there Angular and your 120kb payload). The results above are based on the median times taken from 20 tests per browser/device combination.
The list of tested devices isn’t exhaustive by any means—I just took some of the ones I have sitting around to try and get a picture of how much parse and execution time would vary.
|Device||Browser||Median Parse||Median Execution||Median Total|
|Blackberry 9650||Default, BB6||171ms||554ms||725ms|
|UMX U670C||Android 2.3.6 Browser||168ms||484ms||652ms|
|Galaxy S3||Chrome 32||39ms||297ms||336ms|
|Galaxy S3||UC 8.6||45ms||215ms||260ms|
|Galaxy S3||Dolphin 10||2ms||222ms||224ms|
|Kindle Touch||Kindle 3.0+||63ms||132ms||195ms|
|Geeksphone Peak||Firefox 25||51ms||109ms||160ms|
|Kindle Fire||Silk 3.17||16ms||139ms||155ms|
|Nexus 4||Chrome 36||13ms||122ms||135ms|
|Galaxy S3||Android 4.1.1 Browser||3ms||125ms||128ms|
|Kindle Paperwhite||Kindle 3.0+||43ms||71ms||114ms|
|Droid X||Android 2.3.4 Browser||6ms||96ms||102ms|
|Nexus 5||Chrome 37||11ms||81ms||92ms|
|iPod Touch||iOS 6||26ms||37ms||63ms|
|Nexus 5||Firefox 32||20ms||41ms||61ms|
|Macbook Air (2014)||Chrome 37||5ms||29ms||34ms|
|Macbook Air (2014)||Opera 9.8||14ms||5ms||19ms|
|iPhone 5s||iOS 7||2ms||16ms||18ms|
|Macbook Air (2014)||Firefox 31||4ms||10ms||14ms|
|iPad (4th Gen)||iOS 7||1ms||13ms||14ms|
|iPhone 5s||Chrome 37||2ms||8ms||10ms|
|Macbook Air (2014)||Safari 7||1ms||4ms||5ms|
As you can see from the table above, even in this small sample size the parsing and execution times varied dramatically from device to device and browser to browser. On powerful devices, like my Macbook Air (2014), parse and execution time was negligible. Powerful mobile devices like the iPhone 5s also fared very well.
But as soon as you moved away from the latest and greatest top-end devices, the ugly truth of JS parse and execution time started to rear its head.
On a Blackberry 9650 (running BB6), the combined time to parse and execute jQuery was a whopping 725ms. My UMX running Android 2.3.6 took 652ms. Before you laugh off this little device running the 2.3.6 browser, it’s worth mentioning I bought this a month ago, brand new. It’s a device actively being sold by a few prepaid networks.
Another interesting note was how significant the impact of hardware has on the timing. The Lumia 520, despite running the same browser as the 920, had a median parse and execution time that was 46% slower than the 920. The Kindle Touch, despite running the same browser as the Paperwhite, was 71% slower than it’s more powerful replacement. How powerful the device was, not just the browser, had a large impact.
This is notable because we’re seeing companies such as Mozilla and Google targeting emerging markets with affordable, low-powered devices that otherwise run modern browsers. Those markets are going to dominate internet growth over the next few years, and affordability is a more necessary feature than a souped up device.
In addition, as the cost of technology cheapens, we’re going to continue seeing an incredibly diverse set of connected devices. With endless new form factors being released (even the Android Wear watches quickly got a Chromium based browser), the adage about not knowing where our sites will end up has never been more true.
The truly frightening thing about these parse and execution times is that this is for the latest version of jQuery, and only the latest version of jQuery. No older versions. No additional plugins or frameworks. According to the latest run of HTTP Archive, the median JS transfer size is 230kb and this test includes just a fraction of that size. I’m not even asking jQuery to actually do anything. Basically, I’m lobbing the browsers a softball here—these are best case results.
So what’s a web developer to do?
Render on the server If you’re using a client-side MVC framework, make sure you pre-render on the server. If you build a client-side MVC framework and you’re not ensuring those templates can easily be rendered on the server as well, you’re being irresponsible. That’s a bug. A bug that impacts performance, stability and reach.
There are certainly cases to be made for JS libraries, client-side MVC frameworks, and the like, but providing a quality, performant experience across a variety of devices and browsers requires that we take special care to ensure that the initial rendering is not reliant on them. Frameworks and libraries should be carefully considered additions, not the default.
When you consider the combination of weight, parse time and execution time, it becomes pretty clear that optimizing your JS and reducing your site’s reliance on it is one of the most impactful optimizations you can make.