Tuesday, December 14, 2010

10 tricks that will make your jQuery enabled site go faster

During the last few weeks, I've had the chance to go more in depth with jQyery and general site performance. I've found some techniques that makes my site go much faster. I don't know if they're all best practice, but this article is meant to at least give you some good ideas.


$(document).ready(e) vs $(window).load(e)


The .ready(e) function fires when a dom element is ready. That's why we use it on the document element. When the document element is ready, the page is also, sort of. Actually the page is not ready until the window is fully loaded with images and other resources, but we're allowed to start manipulating the DOM at an earlier stage. I recomend doing your DOM manipulation, resizing, setup menus etc first and then start your ajax calls once the page is fully rendered.

So put your design oriented code in the $(document).ready(e) function and your data oriented code in the $(window).load(e). That way, the page components come to place at an earlier stage and that creates the illusion of speed.


Load JSON from string

In order to avoid the extra cost of doing a page request you can actually include JSON in the page as a string. For instance, I use a jQuery framework to build my menu, but the page lags a bit while waiting for the external scripts that loads the menu elements. I found that the user experience is much faster if I include the menu items as a javascript string at the bottom of the page. The main page will take some milliseconds extra loading, but the menu lagging will dissapear. I then set up the menu in the $(document).ready(e) function and set up the menu before the page data loads.


var menuJSON = '[{....}]'
$(document).ready(function () {
var menuObject = $.parseJSON(menuJSON);
}


Store repositories in memory

If you load JSON or XML from another script with ajax, keep the returned object in a variable in the window scope. That way, you can do live search and sort operations quickly without loading external resources again. I know some like to do sort in the database, but modern browsers can do it quite quick. It depends on the size of the dataset of course.


var userRepository;
$(window).load(function(){
userRepository = $.ajax(....);
doSomething(userRepository);
});


Setup events last

You can save a bit of loading time by adding events last. First layout, then data, and then events. Events aren't visible and we want the visible parts of your web site to load first, right? What you could do is to disable buttons until they're loaded with events. This example uses jQueryUI.



$(document).ready(function(){
$(":button").button("disable");
});


and then, once an event has been added do all your button code:


(window).load(function(){
$("#button").click(....);
$("#button").button("enable");
(...)
});


Unbind events

If you never unbind your events, you could potentially consume quite a lot of unnecessary memory. Even worse you could stack up double events and your click function or keypress trapper could be executed twice. In order to make sure that there's only one click funtion on a DOM element do the following:


$("#button").unbind("click");
$("#button").click(....);


.empty() vs html("")

This one is related to the one above. If you write .html("") when you want to empty a div or a list, then there's no guarantee that the events assigned to the child DOM elements are unbound. The jQuery manual states:

"To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves."

So, always use .empty() in stead of .html("")


Load your javascripts at bottom of the page

The new best practice is to load CSS in the head and javascripts at the end of the body. It actually works. If you do, then the page will have read the rest of the page before starting to manipulate it. Hence it appears much faster.

Since javascripts are getting quite heavy in size, it is actually better to let the page load divs and images before large chunks of javascripts. jQuery is just under 80 kb, jQueryUI another 200 kb and I bet you have a few other scripts as well. It all adds up and makes your site slower.

Also, rumors has it that some web search engines only reads a certain amout of text before leaving for another page, and therefore you will be able to present more of the important stuff first.


Don't use a content delivery system

Unless you run a site with tens of thousands of visitors daily or your bandwith costs are very hight, I see no reason to use a CDN. I think what they are trying to achieve is a caching effect. If your visitors allready have the recent jQuery framework cached from Google, they won't have to when they go to your site. But in my experience, CDNs are always a performance drag. They all tend to go slower than my on web hosting and that looses the whole meaning of using these services.


Download the custom version of jQueryUI

The full version of jQueryUi is just under 200kb in size. If you only use button functionallity, you only touch the tip of the iceberg. The custom version of jQueryUI which only holds the core funtionallity and the button package only takes about 13,9 kb. Do the maths, the custom version takes the jQueryUI from being the heaviest file you load on your page to being on of the smallest.

This also explains a problem with using a CDN, since they only have the large version on their site (probably).


RTFM

I mean it, are you familiar with the special selectors in jQuery? How about the .live(...) funtion? It's all in the jQuery documentation. Use it.



kick it on DotNetKicks.com

7 comments:

pavsaund said...

Great summary Anders. Another point, which may be worth adding, is to reuse your selectors.

$("#id).hide();
$("#id).show();
$("#id).bind(...);
var src = $("#id").attr('src');

could be replaced with

var $id = $("#id").hide();
$id.show();
$id.bind(..);
var src = $id.attr('src');

The example is simple, but saving selectors that get reused is a good way to cut back on the load. Especially if it's something you do across your code.

Also the $-prefix to the variable name is a good way of seperating jQuery selector-variables and standard variables.

Xwero said...
This comment has been removed by the author.
Andrew Davey said...

Instead of "Load JSON from string" why not just "Load object from JSON" directly?
var menuObject = [ { ... } ];
No parsing is required.

australia web development said...

Great post. Thanks for sharing it. Looking forward to reading more.

Dave Van den Eynde said...

While I agree with most of the points you are making, I don't agree about not using a CDN. I use CloudFront all the time. It's significantly faster than my web host. For example, a round trip to CloudFront takes less than 20ms for me, even if only to return a 304 "Not Modified".

Also, you should be familiar with the notion that you should multiple domain names to speed up loading of components as your browser only makes 4 requests to the same host simultaneously. But all of this is not related to jQuery, of course.

Anders said...

@Dave Van den Eynde: I might have to review my statements about using a CDN. In order to test the speed using some of these services, I've set up a simple test (not exactly scientific readings and only tested with Firefox):

http://www.ettsted.com/stuff/2011_01/bootstrapper/index.html

I might have to make some stats in order to compare..

Muhammad Azeem said...

This is a nice article..
Its very easy to understand ..
And this article is using to learn something about it..

c#, dot.net, php tutorial

Thanks a lot..!