Web & Mobile Development JLW288

05.JS.Optimization

Optimization

If we hit that bullseye, the rest of the dominoes should fall like a house of cards. Checkmate.

Optimization

  • A collection of tips and tricks to writing better JS
  • A collection of tips and tricks to making better websites; speedwise and sizewise.
Note: the types of tips are intermingled on purpose, because they're all equally important

Put scripts at the bottom

The problem caused by scripts is that they block parallel downloads. The HTTP/1.1 specification suggests that browsers download no more than two components in parallel per hostname. If you serve your images from multiple hostnames, you can get more than two downloads to occur in parallel. While a script is downloading, however, the browser won't start any other downloads, even on different hostnames.

Including External Scripts

Keep HTTP requests to a minimum

  • Optimize caching by using Expires and Cache-Control: max-age headerfs
  • Collate CSS/JS
    • Combine scripts to get fewer files (and thus less requests!)
  • base64 encode images where possible
    • viz. icons used in CSS
  • Load libraries from a Content Delivery Network

Make it understandable

  • Give your variables a short and easy to understand name
    • Good: age, firstName
    • Bad: createNewMemberIfAgeOverEighteenAndMoonIsFull
    • Exceptions: counters in loops such x and y
  • Don't limit yourself in naming your variables
    • Better to use isLegalAge(18, age) than isOverEighteen() as it gives your more wiggle room

No global loitering

  • Always use the var keyword when declaring variables
  • Use namespaces (Object Literal)
  • Use (revealing) module pattern

Annotate your code

  • Clean “good” code is good but not enough.
  • Code needs comments
    • The right kind of comments
  • Comment the why, not the what
    • The code is the what.

Don't overmanipulate CSS Properties

  • Keep style definitions in your CSS
    • Why add a border of 1px solid red and change the color to red and make the text bold and set the background to something red-ish if you can just add the class .error to an element?
  • Easier to change when needed

Optimize scripts download speed

  • Use shorthands where possible
    • literals, 0px0, #FFFFFF#FFF, etc.
    • A character saved is a character less to download
  • Minify JS/CSS
    • Strip all whitespace, comments, etc. to get smaller files
  • Use HTTP compression (Gzip)
  • Compress images using tinypng, smushit, ImageOptim, etc.
  • Add a few extra DNS CNAME records to your domain to have your server serve more parallel requests

Allow for configuration

  • Users of your scripts will want to customize the output
    • Very easy with jQuery's .extend

Keep DOM lookups to a minimum

  • Optimize Loops
  • Cache DOM lookups and/or make use of chaining

Keep DOM Manipulations to a minimum

  • Bad
    var myList = $('#myList');
    for (var i = 0; i < 1000; i++){
    	myList.append('<li>This is list item ' + i + '</li>');
    }
  • Good
    var myList = $('#myList');
    var myListItems = '';
    
    for (var i = 0; i < 1000; i++) {
    	myListItems += '<li>This is list item ' + i + '</li>';
    }
    
    myList.html(myListItems);

Prevent excessive redraws

  • Bad
    var items = $('li');
    items.css('background-color','red').css('color','lime').css('border','1px solid blue');
  • Good
    var items = $('li');
    items.css({
    	'background-color': 'red',
    	'color': 'lime',
    	'border': '1px solid blue'
    });

Don't trust user data

  • Can easily be manipulated with Firebug
  • Cast vars where possible
    • Always provide a radix when using parseInt

When using jQuery, always use the latest version

  • New versions not only contain new features but also
    • Improvements
    • Bug Fixes
  • jQuery Version Speed Comparison: jsPerf Test

Make good use of bubbling

  • Use a delegate: Don't bind event handlers on 1000 table cells, but bind 1 event handler on the table and let the event bubble up
  • In jQuery
    • Use $.fn.on() with extra selector string to filter the descendants of the selected elements that trigger the event
      $('table').on('click', 'td', function(e) { ... });
    • Never use $.fn.live()
    • Use of $.fn.delegate() is possible, but we prefer the variant of $.fn.on()

Know your selectors

  • The need for speed
    • Fast: #id, element
      • Can be passed directly into native versions
    • Slower: .class
      • No Document#getElementsByClassName in IE5-8!
    • Slowest: pseudo (viz. :visible) & attribute ([title="foo"])
      • Only modern browsers will benefit
      • In jQuery: Try to split those off into sub-selections with .find()
  • Don't overcomplicate selectors
  • Be specific at the end (engines work right-to-left)
  • Not all selectors are created equal: jsPerf Test
    • Use context param or use .find()

Make use of modern code

  • Use requestAnimationFrame() instead of setTimeout()
    • Hardware acceleration!
    • Aware if a tab is active or not
  • Use CSS3 animations instead of changing CSS properties via JS (video)
    • Again: Hardware acceleration!

Go Plain Vanilla

  • “Bad”
    $('a').on('click', function(e) {
    	alert($(this).attr('href'));
    });
  • Better
    $('a').on('click', function(e) {
    	alert(this.href);
    });
  • Best
    document.querySelectorAll('a').addEventListener('click', function(e) {
    	alert(this.href);
    });
  • In modern browsers: Vanilla JS FTW

Questions?

Sources

ikdoeict.be