Increase site performance by cutting down on jQuery (Back to javascript basics)

The past few years

I found myself using jQuery so much, I had forgotten Javascript
It occurred to me some time last year that I had been using jQuery so often for the past few years that I had forgotten many of the fundamentals of Javascript. When jQuery first came out, it was an exciting new technology. Sure, prior frameworks were created to make our lives easier, but jQuery seemed to cover every aspect. It makes animations easy, it turns complicated AJAX calls into a trivial function call and relieves the headache caused by non-compliant browsers.

As accomplished as you may feel, having written so many applications using jQuery, you will eventually come to the same realization that I did. The simplicity of the framework had given me tunnel vision, and without proper studying there is no way I would have even been able to pass the technical Javascript interview. Working at a massive e-commerce corporation doesn’t help either, as it requires developers to understand how to support dinosaur browsers more so than it does encourage you to learn what’s new in the world. My plan began by going back to the basics.

Refactoring the bone yard

With newfound knowledge, I took to an older app written primarily in jQuery, and converted the code to Javascript where I could.
After nearly finishing my first full-on Phonegap mobile application, it dawned on me that ‘this is the best Javascript app I have probably ever created!’. I had followed all best javascript practices, made the entire application within a main closure, several smaller closures for impeccable organization, and handled memory management like a boss. My focus was also on function length, keeping all of the functions a relative size (around 10-20 lines), making functions re-usable and offloading animations to CSS3.

The web application that I started creating nearly 5 years ago that I am still fully supporting (Project Name: Droid Track, aka: Location Over Time, aka: Display Tracks) is a large pit of spaghetti’d out jQuery code. The algorithms and logical workflow that I have in place are actually something to brag about, but the entire app needed a performance assessment and facelift.

I started simple, by following the highly suggested jQuery to Javascript changes to help performance and memory. A few to name:

Changing $(this) to this: $(this) is actually an extra function call, so if you feel it is more convenient, it is better to at least cache it in a variable, but I got rid of them entirely; over 100 instances. Instead, using ‘this’, the native functionality to grab an instance of an object.

Changing any function chained from $(this): Since jQuery has its own custom functions that chain to $(this), the next step was to convert any of those functions to use native Javascript instead. A few common ones were:

Concerning $(this) & this scoped variables
/** $(this) is a function call itself, and has quite a bit of overhead. Caching will help this, but will ultimately always be slower than using JS 'this' keyword and will offer nearly the same result in every case (except for the few differences in type that is returned) */
//Changing jQuery's method to get value
var $thisVal = $(this).val(), thisVal = this.value;
//Same thing here, $(this) is a costly function call, and $.prop() is also a function call, whose sole purpose is to see which browser supported 'get property' function exists
var $isChecked = $(this).prop(‘checked’)), var isChecked = this.checked;

If you are familiar with jsperf, you would know these native functions all run 90%+ faster than any jQuery, and after this refactor, it was obvious.

Created helper functions that mimic jQuery’s/Sizzle’s selector engine: I created utility functions that take in an element from the DOM, and return a blank string rather than null or undefined so that I can select elements without needing to know the status of their existence (since some elements will only be on the page for select user types). This looks something like:

Converting jQuery to Javascript functions
//jQuery selectors cost at least one extra function call, typically more
var $slowSelector = $(‘#someId’);
//Using a helper function, we know it will just involve one helper function and be the fastest possible solution
var fastSelector = getElementByIdNoNull(‘someId’);
//Convert jQuery property checks to use native Javascript with helper functions
var $isChecked = $(‘#someCheckbox’).prop(‘checked’); var isChecked = isCheckedNoNull(‘someCheckbox’); function getElementValueNoNull(element) {
//Check nodeName to ensure it's a JS object, not JQ
if(element !== null && element.nodeName) { return element.value; } else { return ''; } } function isCheckedNoNull(element) { if(element !== null && element.nodeName) { return element.checked; } else { return false; } }
The Result

After having a fully refactored javascript file, I put each build to the test.
I had each of them run side by side multiple times in a cache-less browser and ran several profiles. On average, the entire application would load in 8-9 seconds before the refactor. After the changes, it will now run in 5-6 seconds, a huge, noticeable change for this rather large application. And it wasn’t just the areas that I explicitly changed that felt faster, the entire application was snappier because of the smaller memory footprint.

Conclusion

This was one of the biggest refactors I had done to any of my personal projects, and I must say, my satisfaction level was (still is) through the roof!

This was not only a great change for my application, but for my growth in understanding front end programming. In this time, I was able to fully investigate how jQuery works on a function level, and weed out any functions that were causing too much overhead.

The point of post was to suffocate the belief that shaving a few milliseconds (by using native Javascript) isn’t worth the extra code required. The BIGGEST point that I learned (and hope you take away) from this exercise, was that those milliseconds do matter! This doesn’t mean to sacrifice maintainability, or add too much extra code. Hell, the extra helper functions I created only added another 50 lines of uncompressed code. The next big step will be to transform all jQuery animations to use CSS3 animations, which will hopefully bring around another large round of performance increase.

I always ask, ‘What would Google do?’, and aside from one site (their slowest, ill-performant site under their name http://blog.jquery.com/2007/11/02/google-using-jquery/), they don’t use heavy frameworks, they do it the best way. That is why you always find yourself pleased with Google’s plethora of websites.

2 thoughts on “Increase site performance by cutting down on jQuery (Back to javascript basics)

  1. Pingback: First Phonegap Application: Balancing Javascript, CSS3 & HTML5 | Webdevinci - Web Dev Blog