News

5 jQuery mistakes to avoid to get faster, better code

jQueryLogoDark

jQueryLogoDark

Relying on $(document).ready();

Including JavaScript in the <head></head> tags and then waiting for jQuery to run when the DOM is fully loaded can cause the end user a headache-inducing wait. Executing JavaScript code when the browser has loaded the complete DOM is in itself inherently difficult and troublesome. Each browser tells JavaScript when the DOM is ready at a different time and jQuery has a helpful method – .ready() – that does a multitude of things in the background to ensure the DOM is loaded before firing. JavaScript is a blocking script – meaning when the browser finds the <script> tag it won’t do anything else until that code has loaded in. Any assets, photos, CSS and other JavaScript files, won’t execute until this file is loaded. It’s considered best practice to place all JavaScript assets in the footer as JavaScript should enhance a page, not build the UI. If code is required to execute when all assets in the webpage are ready, it would be convenient to do this. The code doesn’t get executed until the whole DOM is ready – large images slow down the time from page load to the JavaScript firing.

//code//
(function($) {
//fire code
})(jQuery);

Initialising any functions this way enables the JavaScript to execute when it’s possible. The end user will see the page being useable sooner – perceiving a faster load time. If specific code needs to ensure a certain element is completely loaded before being executed, use the following:

.load():
$(img).load(function(){
//execute code
})

Hosting jQuery yourself

When building a website that utilises jQuery it’s all too easy to download a copy of the library, place it in a local directory then load it in to the pages required.

<head>
<script src='/jQuery.js'></script>
</head>

For every new visitor to a website they have to download this file from the server, which slows down the initial page load and introduces an extra drain on bandwidth. Reference jQuery from a CDN and the chances are that when someone visits the website, they will previously have visited a website that hosts jQuery with that CDN (Google for example) and already have jQuery stored in the browser’s cache, reducing bandwidth and page-load time.


Faster selectors

With the introduction of CSS preprocessors, it’s become a bit of an issue with overly specific CSS declarations yet with jQuery – we find the opposite happening. Look at this navigation code:

<ul id="navigation">
<li><a class="nav-item" href='#home'>Home</a></li>
<li><a class="nav-item" href='#about'>about</a></li>
<li><a class="nav-item" href='#contact'>contact</a></li>
</ul>
<script>
$('.nav-item').click(function(){
//code to scroll to location
})
</script>

The lack of specificity here means that jQuery has to traverse the whole DOM to find .nav-item – on big pages this can reduce performance greatly. It’s like going shopping and having to look at every item in the shop to find a specific item. You can increase performance by increasing selector specificity:

<ul id="navigation">
<li><a class="nav-item" href='#home'>Home</a></li>
<li><a class="nav-item" href='#about'>about</a></li>
<li><a class="nav-item" href='#contact'>contact</a></li>
</ul>
<script>
$('#navigation .nav-item').click(function(){
//code to scroll to location
})
</script>

Now when traversing the DOM, jQuery looks for the parent id (#navigation) and then looks for its child element with the class declared. Going back to the shop analogy, the aisle would now be known as (#id), thus searching for the specific item would take much less time than before.


Not caching DOM elements

Here is a simple script for adding a class to a website’s navigation, then removing that class after executing other logic:

$('#navigation').addClass('visible');
//execute other code
$('#navigation').removeClass('visible');

Every time jQuery wants to alter the navigations class attributes, it has to traverse the whole DOM and find the element with the id #navigation, alter its class then continue processing the next line of JavaScript. Each time the $(‘selector’) is used, jQuery has to look for this element in the DOM. Assign the jQuery $(‘selector’) object to a variable increases performance, as a reference to that element is now available in memory.

var $navigation = $('#navigation');      
$navigation.addClass('visible');
//execute other code
$navigation.removeClass(‘visible');

Animating with jQuery

When jQuery was initially released its internal animation engine was one of the most ground-breaking features – since then browsers and CSS have moved considerably forward. Take this example of animating an element’s height for example:

$('.changeHeight').animate({
'height' : 250
}, 650);

JQuery internally calculates the element’s height, then changes the height up to 60 times a second, causing the browser to redraw the DOM every single time it’s changed (60fps). CSS animations in modern browsers are handled using hardware acceleration and are processed by the GPU ensuring a faster experience over CPU tasks like rerendering the DOM for example.

<style>
.changeHeight{
-webkit-transition: all 0.65s ease-in-out;
-moz-transition: all 0.65s ease-in-out;
-o-transition: all 0.65s ease-in-out;
transition: all 0.65s ease-in-out;
overflow:hidden;
height:auto;
max-height:0;
display:block;
}
.open{
max-height:250px;
}
</style>
<script>
$('.changeHeight').addClass('open');
</script>
×