41
Unlearning and Relearning jQuery Client-side Performance Optimization Oct 14, 2010 1 Created for Magma Rails 2010 - www.magmarails.com

Unlearning and Relearning jQuery - Client-side Performance Optimization

Embed Size (px)

Citation preview

Page 1: Unlearning and Relearning jQuery - Client-side Performance Optimization

1

Unlearning and Relearning jQuery

Client-side Performance Optimization

Oct 14, 2010 Created for Magma Rails 2010 - www.magmarails.com

Page 2: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 2

Purpose and Audience

• Purpose– Understand why client-side performance optimization is important– Better understand jQuery and how to maximize performance when

using it

• Audience– Has a very basic understanding of client-side web development

• JavaScript, HTML, CSS

– Ideally, has used some JavaScript framework before• jQuery, Prototype, YUI, MooTools, etc.• If you haven’t specifically used jQuery before that’s fine. The API

documentation will fill in the blanks later!• If you’ve never used a framework before that’s fine too, this will begin to

make more sense later as you write your first jQuery application.

Oct 14, 2010

Page 3: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 3

Why care about the performance of client-side code?

• Myth: “It doesn’t run on my servers so it’s not important to the speed of my application.”

• Fact: Users of your website judge the performance of your application based on how long it takes for them to begin using it, not how long it takes to process and render a request on your servers– This is includes:

• Number of requests for files to the server (this is a big deal)– Use sprites: http://css-tricks.com/css-sprites/– Compress JavaScript and CSS files into a single file of each type when possible:

http://developer.yahoo.com/yui/compressor/

• The total size of content download• The amount of time it takes to render the page• The amount of time it takes until the page is ready to be interacted with• How long it takes to process each interaction with the page

• This means that perceived performance is just as important as actual performance! We’ll talk about techniques that apply to both

Oct 14, 2010

Page 4: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 4

Why use a JavaScript framework?

• Deals with browser inconsistencies for you• You have to write a lot less code• Lots of community contribution and therefore a more stable

core for your JavaScript application• You can upgrade to a newer version later and improve your

application for free• Did I mention that you get to write less code?

Oct 14, 2010

Page 5: Unlearning and Relearning jQuery - Client-side Performance Optimization

5

Why jQuery and not Prototype?

• Easier to use than Prototype• Usually results in fewer lines of code• jQuery has a smaller footprint• By far the most popular JavaScript framework

– About 28% of all websites on the internet use it– The big players use it (google, twitter, amazon, etc.)– This means more community support and more contribution to the

open source code

Oct 14, 2010 Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com

Page 6: Unlearning and Relearning jQuery - Client-side Performance Optimization

6

Using jQuery with Ruby on Rails

• For Rails 3– Use the Unobtrusive JavaScript library at

http://github.com/rails/jquery-ujs– In Rails 3 the JavaScript helpers no longer mix JS with your markup

(this is a very good thing!) allowing us to easily swap out JS frameworks with just a single JS file

– More instructions at http://joshhuckabee.com/jquery-rails-3

• For older versions of Rails– Use the jRails plugin from http://github.com/aaronchi/jrails– Replaces the default helpers in Rails to output jQuery code instead of

Prototype

Oct 14, 2010 Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com

Page 7: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 7

What you probably already know

• You can access elements in a page using a CSS selector– $(‘#myDiv’) instead of document.getElementById(‘myDiv’)

• In Prototype this would be $(‘myDiv’) since the $ method looks up an element based on its ID

– $(‘.someClass’) gives you an array of all elements having a particular class

• In Prototype this would be $$(‘.someClass’) since the $$ method is the one used for selecting elements via a CSS-style selector

– You can do fun things like:• Show and hide elements on a page

$(‘#myDiv’).show()$(‘#myDiv’).hide()

• Make things happen when you click on an element

$(‘#myDiv’).click(function(){ alert(‘clicked!’) })

• …and a bunch of other stuff tooOct 14, 2010

Page 8: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 8

What you may not know

• Some selectors can be very slow• You don’t need to use $() every time you want to select an

element• You can chain jQuery method calls

– Usually a good idea, but not always (more on this later)

• You may be writing fewer lines of code with a JS framework but it can still make your application much slower if used improperly– This goes for all frameworks, including Prototype

• jQuery !== JavaScript• jQuery is NOT all-powerful!

– You still need to understand how JavaScript works without it!

Oct 14, 2010

Page 9: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 9

The DOM (Document Object Model)

• Think of it as a JavaScript API for accessing HTML elements and manipulating them

• Get an element with a particular ID– document.getElementById(‘myDiv’)

• Redirect to another page– window.location = ‘http://example.com’

• Get all elements with a particular tag name– document.getElementsByTagName(’div’);

• All browsers support these• You want to favor jQuery use that directly

maps to a built in DOM method because they will be the fastest

Oct 14, 2010

Image courtesy of John M. Kennedy T. http://en.wikipedia.org/wiki/File:JKDOM.SVG

Page 10: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 10

The DOM (Document Object Model)

Terminology I’ll use• Descendent: All elements contained

within that element• LINK and ANCHOR are descendents of DOCUMENT • TEXT and RADIO are descents of FORM• TEXT and RADIO are also descendents of DOCUMENT

• Ancestor: The opposite of descendent• FORM is an ancestor of TEXT and RADIO• DOCUMENT is the ancestor of FORM, TEXT, RADIO, LINK,

and ANCHOR

• Parent: The direct ancestor of an element (only one)

• FORM is the parent of TEXT and RADIO• DOCUMENT is the parent of LINK and ANCHOR

• Children: The direct descendents of an element

• TEXT and RADIO are children of FORM• TEXT and RADIO are not children of DOCUMENT (they are

descendents)• LINK and ANCHOR are children of DOCUMENT

Oct 14, 2010

Image courtesy of John M. Kennedy T. http://en.wikipedia.org/wiki/File:JKDOM.SVG Note: Examples are for the image to the right, not true for all pages

Page 11: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 12

The difference between DOM Ready and onload

• You can’t access a DOM element until it has been fully loaded and rendered by the browser

• onload occurs after everything on the page has been loaded– HTML– Stylesheets– JavaScript (including 3rd party!)– Images– Content of iframes– Comes with the browser

• window.onload = myFunction;• <body onload=“myFunction();”>

• DOM Ready occurs when the document has been processed and all DOM objects are ready for manipulation– Doesn’t wait for assets since they aren’t part of the DOM– jQuery and Prototype give you this functionality

Oct 14, 2010

Page 12: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 13

How do I choose?

• Put application-critical JavaScript in a DOM Ready block– When you can’t use your application without it– Example: critical event listeners

• $(‘#myButton’).click(loadImportantForm);

• Use onload for anything non-critical– Deferring to onload is a good idea when possible because too much

code in DOM Ready can cause the rendering of your page to stall, adding additional time until the user can interact with it

– Example: initializing animations• $(‘#myDiv’).hover(sillyFadeOver, sillyFadeOut);

Oct 14, 2010

Page 13: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 14

When do I need DOM Ready / onload?

• Simple answer: when the browser loads your JavaScript before it loads the DOM elements you need

• When you define your JavaScript in external files– Usually you include these in the header. This means that the

JavaScript file is fully loaded an begins to execute before the browser begins to load the body of your document.

– Sometimes you also include JS files within the body of your document. In this case you don’t know when the file will be ready to execute. Could happen before your DOM is ready or after it.

• When you use inline JavaScript before all required elements have been loaded

Oct 14, 2010

Page 14: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 15

Does that mean I don’t always need it?

• Yes, but be careful. When in doubt, use DOM Ready or onload• This will work

<a id=“myAnchor” href=“#”>click me if you can</a><script>document.getElementById(‘myAnchor’);</script>

• This will not<script>document.getElementById(‘myAnchor’);</script><a id=“myAnchor” href=“#”>click me if you can</a>

• This will work in some browsers but IE < 8 will have a fit<body>  <div>   <script type="text/javascript"> var newElem = document.createElement(’div');     document.body.appendChild(newElem);    </script> </div></body> (so don’t try to use element before it has been closed)

• This applies to jQuery syntax as wellOct 14, 2010

Page 15: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 16

Using DOM Ready and onload

• Onloadfunction myFunction(){ // your code}window.onload = myFunction; // replaces onload with this function, so can only have this once

• Onload (jQuery style)

$(window).load(function(){ // can have multiple on a page

// your code});

• DOM Ready– jQuery only and can have multiple DOM Ready blocks on a page– Longer format

$(document).ready(function(){ // your code});

– Short version

$(function(){ // your code});

Oct 14, 2010

Page 16: Unlearning and Relearning jQuery - Client-side Performance Optimization

17

Common mistake with DOM Ready

• Don’t define methods in a Dom Ready block, just call them– Works

function myFunction(){ // your code}$(document).ready(function(){ myFunction();});– Doesn’t work

$(document).ready(function(){ function myFunction(){ // your code } myFunction();});

Oct 14, 2010 Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com

Page 17: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 18

Getting elements faster

• Always start with an ID– $(‘#myDiv’)– Behind the scenes, jQuery can use the native document.getElementById() which is very fast

– Fastest way to get a DOM element

• Avoid the class selector on a large DOM node– $(‘.myClass’)– Very slow over a large DOM node– No native DOM call common to all browsers

• Use a tag name when possible– $(‘div.myClass’) is much faster than $(‘.myClass’)– Uses document.getElementsByTagName() behind the scenes– But remember that ID is the fastest so $(‘div#myDiv’) is actually

slower than $(‘#myDiv’)

Oct 14, 2010

Page 18: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 19

Getting elements faster

• Optimize selectors using the ‘right to left’ model– As of jQuery 1.3 this the method the selector engine uses

• This means the most specific (right-most) selector is found first and then its ancestors are checked starting on the left

• Make your right-most selector very efficient• Example

– $(‘.myClass div.otherClass’) is actually more efficient than– $(‘div.myClass .otherClass’)

• However, descending from an ID is still the fastest:– $(‘#myDiv div.otherClass’)

Oct 14, 2010

Page 19: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 20

Cache your DOM lookups

• A call to $() returns a valid jQuery object, so store it for later use

• This is bad because each line does a DOM lookup$(‘#myDiv .myClass’).click(myFunc);$(‘#myDiv .myClass’).css(‘width’, ‘250px’);$(‘#myDiv .myClass’).css(‘color’, ‘red’);

• This is much bettervar myStuff = $(‘#myDiv .myClass’);myStuff.click(myFunc);myStuff.css(‘width’, ‘250px’);myStuff.css(‘color’, ‘red’);

Oct 14, 2010

Page 20: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 21

Work with the most specific DOM element possible

• $(‘#myDiv .myClass’) is much faster than $(‘.myClass’)• Use the find() jQuery method to search for matching

elements within your cached objectvar myDiv = $(‘#myDiv’);myDiv.find(‘.myClass’).hide();myDiv.find(‘input’).click(myFun);

• A lot of times it makes sense to cache the main elements of your page up front and use them latercontent = $(‘#content’);sidebar = content.find(‘#sidebar’);article = content.find(‘#article’);commentWrapper = article.find(‘#comments’);comments = commentWrapper.find(‘div.comment’);

Oct 14, 2010

Page 21: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 22

Use chaining

• Remember that a call to $() returns a valid jQuery object, which means you can chain jQuery methods

• You can shorten the previous example:$(‘#myDiv .myClass’).click(myFunc);$(‘#myDiv .myClass’).css(‘width’, ‘250px’);$(‘#myDiv .myClass’).css(‘color’, ‘red’);

• To the lighter-weight:$(‘#myDiv .myClass’).click(myFunc).css(‘width’, ‘250px’).css(‘color’, ‘red’);

Oct 14, 2010

Page 22: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 23

When not to use chaining

• Be careful chaining the DOM traversal methods– Doing so means that your application may be too dependent on the

DOM structure– Example of what not to do:

• $(‘#myDiv’).parent().parent(); // fails if you add another element surrounding this one

– Potential alternatives:• $(‘#myDiv’).parents(‘someTag’)• $(‘#myDiv’).parents(‘.someClass’)

• Not about performance, but about writing good code– Yes, the DOM structure still matters in the last two examples but it

isn’t so rigid that you can’t add or remove elements in between– And yes, the last two examples may be a little slower but not so much

that it’s worth writing unsafe code

Oct 14, 2010

Page 23: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 24

Avoid as much DOM manipulation as possible

• Rendering changes to the DOM is very expensive, so do as few manipulations as possible

• Example of what not to do:<div id=“myDiv”></div><script>for(var i=0; i < 100; i++){ $(‘#myDiv’).append(‘<a href=“#”>link</a>’); // The

browser has to re-render this and any other effected elements at each iteration of the loop

}</script>

Oct 14, 2010

Page 24: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 25

Avoid as much DOM manipulation as possible

• It would be much more efficient to store all elements you wish to create in a string and then insert them one time:<div id=“myDiv”></div><script>myLinks = ‘’;for(var i=0; i < 100; i++){ myLinks = myLinks + ‘<a href=“#”>link</a>’;}$(‘#myDiv’).append(myLinks); // this is the only DOM

manipulation

</script>

Oct 14, 2010

Page 25: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 26

Avoid as much DOM manipulation as possible

• It would be even more efficient if we wrap many individual elements in a single element and then insert that in the DOM:<div id=“myDiv”></div><script>myLinks = ‘<div id=“myDiv”>’;for(var i=0; i < 100; i++){ myLinks = myLinks + ‘<a href=“#”>link</a>’;}myLinks = myLinks + ‘</div>’;$(‘#myDiv’).replaceWith(myLinks); // instead of putting a

string of 100 elements in this div we are replacing a single DOM node

</script>

Oct 14, 2010

Page 26: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 27

Avoid as much DOM manipulation as possible

• Don’t like the idea of creating a string for your DOM elements?• Since rendering is the most expensive part, use the clone() jQuery

method to make a copy of the DOM object that you can manipulate without being rendered and then insert that object into the DOM when finished<div id=“myDiv”></div><script>clonedDiv = $(‘#myDiv’).clone();for(var i=0; i < 100; i++){ clonedDiv.append(‘<a href=“#”>link</a>’); // clonedDiv is

not visible on the page so manipulating it doesn’t cause the browser to re-render

}$(‘#myDiv’).replaceWith(clonedDiv); // still the only time re-

rendering occurs

</script>Oct 14, 2010

Page 27: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 29

Event delegation

• Events in jQuery “bubble” up to their parent DOM elements unless you tell them not to

• You can use this to your advantage by creating a single event listener on a parent object and letting that listener determine which of its children triggered the event

• This is much more efficient than creating a many listeners on individual elements

• If you’re only binding one or two event listeners then this method isn’t really necessary

Oct 14, 2010

Page 28: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 30

Event delegation

• Let’s say you have a div with 100 anchor tags and you want to hide the anchor when it’s clicked

• Instead of:$(‘#myDiv a’).bind(‘click’, function(){ $(this).hide();});

• Do this:$(‘#myDiv’).bind(‘click’, function(e){ if(e.target.nodeName.toLowerCase() === 'a'){ $(e.target).hide() }});

• e is the Event object• Notice that e.target returns the actual DOM node, not a jQuery object,

so you need to pass it to $() to get jQuery functionalityOct 14, 2010

Page 29: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 31

jQuery.delegate()

• This is the same example using jQuery’s built in event delegation method (1.4.2 and above)

$('#myDiv').delegate('a', 'click', function(e){ $(this).hide();});

• Tip: for this and the last example, use e.preventDefault() to prevent the default action of the event. In this case, following the hyperlink:

$('#myDiv').delegate('a', 'click', function(e){ e.preventDefault(); $(this).hide();});

Oct 14, 2010

Page 30: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 32

Lazy-loading assets

• Load the bare minimum up front and load the rest as needed• Initial load and rendering of the page is much faster, allowing

the user to interact with the page as quickly as possible• Works well in many cases but sometimes waiting for

something to load after the user begins to interact with the page is more frustrating, so choose wisely when it’s appropriate

• An excellent choice for non-critical 3rd party tracking scripts, especially ones that are notorious slow

• Can apply to JavaScript files, images, even CSS

Oct 14, 2010

Page 31: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 33

Lazy-loading assets

• Method 1: document.write()• Can also apply this method to other types of assets such as

images and CSS<script> document.write('<script src="', ’someScript.js', '" type="text/javascript"><\/script>');

</script>

Oct 14, 2010

Page 32: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 34

Lazy-loading assets

• Method 2: Change the src property of an existing script tag• This example is just for JavaScript but you could do

something similar for other assets<script id=”lazy" type="text/JavaScript"></script><script> document.getElementById(’lazy').src = ‘someScript.js';

</script>

Oct 14, 2010

Page 33: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 35

Lazy-loading assets

• Method 3: Use AJAX• Applies to any type of asset• Just add an AJAX call on DOM Ready to grab what you need• Check out the jQuery documentation on using AJAX:

http://api.jquery.com/category/ajax/

Oct 14, 2010

Page 34: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 36

Lazy-loading assets

• Method 4: Use the Lazy Load jQuery plugin: http://www.appelsiini.net/projects/lazyload

• When you want to lazy load images on a very long page• Let’s you load images visible in the browser first and delay

loading of images “below the fold” (below the current browser view)

• Simplest example: $("img").lazyload(); // causing images below the fold to be lazy

loaded

• Start loading images when they are 200px below the fold:$("img").lazyload({ threshold : 200 });

Oct 14, 2010

Page 35: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 37

Unobtrusive JavaScript

• Keep JavaScript in external files and avoid inline JavaScript (Rails 3 does it!)

• Less code for the browser to load and interpret while rendering

• JavaScript in external files can be cached by the browser. Inline JavaScript can’t be cached

• Avoid:<a href=“#” onclick=“myFunc();”>run myFunc</a>

• In favor of:<a href=“#” id=“myLink”>run myFunc</a>$(‘#myLink’).bind(‘click’, myFunc); // in external file on

DOM Ready

Oct 14, 2010

Page 36: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 38

Unobtrusive JavaScript

• Rails 3 is a great inspiration for more advanced uses• Uses custom attributes to indentify what events to bind on elements• Rails helper code:

<%= link_to "delete", domain_path(@domain), :method => :delete, :confirm => "Are you sure?" %>

• In Rails 2 this outputs a real mess:<a href="/domains/1" class="destroy" onclick="if (confirm('Are you

sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'pKvg9hsnQ33uk='); f.appendChild(s);f.submit(); };return false;">delete</a>

• In Rails 3 the markup just looks like this:

<a href="/domains/1" data-confirm="Are you sure?" data-method="delete" rel="nofollow">delete</a>

– An external JavaScript file (remember jquery-ujs?) uses the attributes and binds the appropriate JavaScript to the element

Oct 14, 2010

Examples from http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/

Page 37: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 39

Storing data on DOM objects

• Sometimes you need to store extra information about an element to improve efficiency, keep yourself from having to pass a bunch of variables through method calls, etc.

• It’s tempting to do one of the following:– $(‘#myElement’).attr(‘rel’, ‘some data’); // improper use of attribute

var data = $(‘#myElement’).attr(‘rel’);– $(‘#hiddenInput’).val(‘some data’); // unnecessary form data

var data = $(‘#hiddenInput’).val();

• jQuery gives you a much nicer alternative:– $(‘#myElement’).data(‘key’, ‘value’); var data = $(‘#myElement’).data(‘key’);

• Note: you can also store data on a DOM object directly using standard object syntax since a DOM object is the same as any other object. Just don’t store it on a jQuery object unless you use data()

– var elem = $(‘#myElement’).get(0); elem.foo = ‘bar’; alert(elem.foo);– But data() is safer so you generally just want to use that

Oct 14, 2010

Page 38: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 40

Use for instead of each()

• The native for loop is much faster than jQuery’s each() iterator so use it when possible for large arrays

• Instead of:$.each (array, function (i) { // do something with array[i]});

• The same can be done with a native for loop:for (var i=0;i<array.length; i++) { // do something with array[i]}

Oct 14, 2010

Page 39: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 41

Use short variable names and create aliases

• Reduces overall size of file, especially if not minified• Only useful when these items are used frequently in a large JS application• Does reduce code readability so good minification may be a better option in many

cases, but some of these may not be minified so watch outvar w = window, l = w.location, d = document, t = true, f = false, n = null, M = Math, o = "object", a = "array", s = "string”, u = "undefined";

l = ‘http://jonathandean.com’; // redirect to another page

if(myVar == f || myVar == n) // test if myVar is false or nullOct 14, 2010

Page 40: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 42

Other client-side performance tips

• Make the fewest number of requests to the server as possible– Each request adds overhead and additional time to load– Combine multiple small images into a single sprite– Combine JS and CSS into a single file of each type when possible– Don’t load a file you don’t need

• Compress JS and CSS to remove whitespace characters and shorten long variable and method names

• You don’t necessarily want to create “packed” files– These files will have the smallest total size– However, the browser needs to read in the entire file and parse it

before it can be used. The parsing step is not cached and adds overhead to each page load. Often the benefit does not outweigh the cost

Oct 14, 2010

Page 41: Unlearning and Relearning jQuery - Client-side Performance Optimization

Unlearning and Relearning jQuery (Client-side performance Optimization) by Jonathan Dean - www.jonathandean.com 43

Download for later

• You can find these slides sometime tomorrow at http://www.jonathandean.com/2010/10/unlearning-and-relearning-jquery-client-side-performance-optimization/

• The short URL is http://tinyurl.com/jquery-magma • Check http://jonathandean.com soon for an HTML version of

the presentation (after a few more caguamas and a long flight home!)

Oct 14, 2010