How to improve jQuery performance

You have probably ever heard of best practices to improve your website’s quality and performance (configure a cache policy, enable gzip compression…).
However, web performance doesn’t stop to follow general best practices: each technology has its own specific recommendations. Some mistakes are quite trivial, but some others can be painful for your website. The addition of several minor errors can really slow down your final product. That’s why you should always think about performance upstream and during the development step.

At DareBoost, we love to quote this declaration from Larry Page (Google Founder) :

As a product manager you should know that speed is product feature number one.

 

jquery-logo
This article is about jQuery most common mistakes that you may be faced. That’s nessessary to be vigilent when you’re using some front-end frameworks, like jQuery, especially when you handle a lot of data.

There are often many alternatives for the same functional result. For instance, you can use several kinds of selectors to identify the same node in the DOM:

$("#myElement");
$(".myClass #myElement");
$("#myContainer .myClass #myElement");
...

But which one is the most efficient? What the others really do?
This blog post introduces the basics about some good and bad uses of this framework.

Use ready event only if needed

When you’re using jQuery, one of the firsts line you write is:

$("document").ready(function() {
});
// or alias $(function() {});

The code called into the ready method will be executed once the DOM is loaded. So, any portion of code requiring the use of DOM must be called in this function. Otherwise, JavaScript code called outside the ready method will be executed immediately.

Here’s a simple test to check the difference. I’ve put this JavaScript code at the end of the head tag:

<script src="jquery-1.10.2.min.js"></script>
<script type="text/javascript">
    $("document").ready(function() {
        console.log("READY EVENT (B) => " + (new Date().getTime() - performance.timing.navigationStart) + 'ms');
    });
    console.log("END OF HEAD TAG (A) => " + (new Date().getTime() - performance.timing.navigationStart) + 'ms');
</script>

With an empty body tag:

<body></body>

You can observe the different results:

end of head tag (A) ready event (B) difference (B – A)
~85ms ~108ms ~23ms

The gap increases when the DOM contains more elements. You can check the results for the same test with a 40kB file:

end of head tag (A) ready event (B) difference (B – A)
~85ms ~152ms ~67ms

DOM Manipulation

Sometimes, it’s very useful to update the DOM with JavaScript. But manipulating the DOM is resource intensive. So, respect this rule: NEVER modify the DOM into a loop. That’s one of the worst mistake you can do. You should prefer to store the new content into a variable, and append it AFTER the loop. Then, your DOM is manipulated only once.

// append() is called 100 times
for (var i = 0; i < 100; i++) {
  $("#list").append(i + ", ");
};
// append() is called once
var html = "";
for (var i = 0; i < 100; i++) {
  html += i + ", ";
}

$("#list").append(html);

 

Check out how many operations per seconds are possible in both cases:

append
source: http://jsperf.com/append-on-loop/2

Here, the figures speak for themselves, aren’t they?
Another way could be to extract your element from the DOM (remove() method), treat it and put it back.

Optimize jQuery selectors

There are a lot of things to say about the jQuery selectors. Here, I will just talk about the very basics you have to know.
The jQuery framework is reading selectors from right to left. You will always have to specify the most precise selectors (select by ID is the fastest), and mentioning the most specific selector on the right. Just one example:

// the most efficient
$( "#container" )
// the most precise selector on the right
$( ".myClass1 div.myClass2" )

If the element you want to select has an id attribute, you should not have other selection pattern than the ID itself (it would be pointless):

// bad way
$( ".myClass1 #container" )
// good way
$( "#container" )

More details are available on http://learn.jquery.com/performance/optimize-selectors/.

Do not be jQuery abusive

Sometimes you may consider using classic JavaScript methods if the performance is a critical point for you. For instance, the “for” loop will be more efficient than the jQuery “each” method, and using the querySelector API is better than using a jQuery selector.

Prioritize Above The Fold (ATF) content

In many cases, libraries like jQuery are used to enhance the user interactivity with the page. So you should consider to load and execute your jQuery code once the user is able to interact with your website, ie after the ATF content is rendered.

Use promises

Our last advice concerns code quality more than pure performance. JavaScript is very (too much? :-)) flexible and widespread. There are no exact rules to respect when you’re writing your code. You can quickly be exposed to the famous “spaghetti code”. This will lead to time wasting, mistakes, and sometimes to discouragement, requiring a refactoring. And are you so proud of your comments that they will solve the problem? That’s a common pain and no doubt that you have ever been exposed to this kind of issue.

The code quality topic could be the subject of an entire article, talking about our experiences. But concerning jQuery, you can consider this little tip. I will take a more and more used example: the ajax requests to load content asynchrounously. Sometimes, you are tempted to chain requests.

One way (the bad one) to do the job with jQuery will be:

$.ajax({
   url: "/firstAction",
   success: funtion() {
       //whatever
       secondAction();
       return false;
   },
   error: error()
});

var secondAction = function() {
   $.ajax({
       url: "/secondAction",
       success: funtion() {
           // whatever
       },
       error: error()
   });
};

You should rather use the promises interface implemented by jQuery. So the code above becomes:

$.when($.ajax( { url: "/firstAction" } ))

// do second thing
.then(
    // success callback
    function( data, textStatus, jqXHR ) {},
    // fail callback
    function(jqXHR, textStatus, errorThrown) {}
)

// do last thing
.then(function() {});

Shorter, more elegant and more readable.

And you? Do you know some jQuery performance tips? Feel free to share them with us! You can also test your website concerning the most of these tips thank’s to the DareBoost online tool!

7 thoughts on “How to improve jQuery performance

    1. typo in typo comment
      ——————-
      copy pasta error
      ———————-
      we are talking about spaghetti code but this is ridiculuous

  1. Here’s a simpler implementation of promise.


    $.when( // do first thing )
    .then( // do second thing )
    .then( // do third thing )
    .then( // do last thing );

Comments are closed.