Optimize your JavaScript, CSS and HTML code

How to optimize your JavaScript, CSS and HTML code. Please add to and improve upon the techniques that already listed.

Overview

Code optimization is now an important task with the Web Experience Toolkit taking a mobile-first approach in version 3.0. Where sluggish code may have minimal impact on desktop browser performance, it can result in very noticeable delays on mobile devices. That is why a main focus of WET v3.x is performance optimization.

The WET v3.x framework is already heavily optimized using code minification, consolidation and Base64 encoding. All of these result in significant performance increases but can still be bogged down by bloated and sluggish code. This page provides many tips for ensuring your code is as efficient as possible.

JavaScript code optimization

  • Minimize the use of jQuery: jQuery can be a big help with DOM traversal and complex scripting scenarios but can be sluggish when dealing with simple and straight forward coding scenarios. There is a performance cost to each jQuery object created and jQuery wrapper methods for native JavaScript operations. Avoid creating jQuery objects wherever possible, especially in loops.
  • Optimize your loops: The fastest loops in JavaScript are cached for loops (length cached outside the loop). Avoid using jQuery loops (e.g., each()) wherever possible as there is a lot of overhead. In the case of jQuery objects, use .get() to get an array of DOM objects upon which reverse while and cached for loops can be used. '''Cached for loop (length cached outside the loop):'''
    var i,
    	len = myArray.length;
    for ( i = 0; i !== len; i += 1 ) {
    
    	// do something with array item
    	console.log( myArray[ i ] );
    }
  • if/else versus switch statements: When deciding how to control your program flow, it's important to consider the number of different conditions you need to test. If there are only 1 or 2 conditions, if/else statements are generally faster. However, once you have 3 or more conditions to test, a switch statement is the faster option. Your if/else and switch statements should also be organized so that the most common conditions appear at the top of the if/else block or switch statement (see the jsPerf if/else versus switch test case).
  • Cache DOM elements, jQuery objects and object/array values: There is a lot of overhead to performing DOM searches, creating jQuery objects, and retrieving object/array values. Minimize the impact by caching the results where those results will be used more than once. It is best to store those results in local variables and reuse those variables.
  • Minimize reflow: Every change you make to the DOM has a significant performance cost as it causes page reflow. Minimize this cost by doing all the changes in a single operation to trigger reflow only once versus multiple operations which trigger reflow multiple times. This can be done in the following ways:
    • Put all the changes in a string or object and then append it to the DOM or replace part of the DOM with that string or object.
    • Detach an element from the DOM, make the changes to it, then reattach it to the DOM.
  • Avoid global DOM searches: The performance cost is much greater when searching the whole DOM rather than searching only a small part of it. If you already have a cached search, then take advantage of it and search from that point rather than searching the whole DOM again. For instance if you already have the search for the .button class already cached in the variable $buttons, then do $buttons.find( "a.mybutton" ) to find the a elements versus $( "a.mybutton" ). Where possible, use native JavaScript for searching such as getElementById and getElementsByTagName.
  • Optimized DOM searches first, filtering later: The fastest DOM searches in JavaScript are by id and tag name because of the native JavaScript function getElementById and getElementsByTagName. Take advantage of this performance by doing optimized searches first then filtering later. For instance, instead of .find( "a[href=*'url_fragment']" ) do .find( "a" ).filter( "[href=*'url_fragment']" ).
  • Binding multiple events to an element: When binding multiple events to an element, it is faster to bind all events to a single event handler. You can then use the event's type property to determine which event has been triggered (see the jsPerf handling multiple events test case).
    // Faster: single event handler for both events
    $( "#elem" ).on( "mouseover mouseout", function( event ) {
    	if ( event.type === "mouseover" ) {
    
    		// mouseover
    	} else {
    
    		// mouseout
    	}
    });
    
    // Slower: separate event handler for each events
    var $elem = $( "#elem" );
    $elem.on( "mouseover", function( event ) {
    
    	// mouseover
    });
    $elem.on( "mouseout", function( event ) {
    
    	// mouseout
    });

Testing your optimizations

To test your optimization changes, wrap a block of code with the following two lines of code.

var test = ( new Date() ).getTime();
// Code to test
console.log( ( new Date() ).getTime() - test );

Another option is to use a site like jsPerf to benchmark different JavaScript code snippets.

jsPerf Test Cases

Additional techniques

CSS code optimization

  • Minimize class names: CSS class names are often reused multiple times within CSS and HTML files so can quickly add bulk to files if they are unnecessarily long. Keep class names as short as possible while ensuring they remain unique. A recent WET core framework class name shortening exercise resulted in a 10% to 30% decrease in file sizes.

Additional techniques

HTML code optimization

  • Minimize the use of HTML comments: Every kilobyte counts when it comes to mobile devices so avoid unnecessarily bloating your code with HTML comments. Keep comments to the bare minimum by eliminating unnecessary comments and shortening the rest.
  • Remove commented out code: Commented out code should not be left in production Web pages. Commented out code can easily add many unnecessary kilobytes to downloads. Keep unused code separate from production Web pages.
  • Use tabs instead of spaces to indent code: It can take an average of 5 space characters to equal the indent of 1 tab character. Significant file size savings can be achieved by using tabs instead of spaces. Many editing tools provide the ability to quickly switch to indenting with tabs.
  • Minimize indenting: Indenting is helpful for code clarity but can quickly add to the HTML file size. Find a good balance between code clarity and file size to minimize the impact on the end user.
  • Remove the type attribute from script elements: In HTML5, type="text/javascript" is no longer required on script elements. Only use the type attribute on script elements for non-JavaScript scenarios.
  • Remove the type attribute from style elements: In HTML5, type="text/css" is no longer required on style elements. Only use the type attribute on style elements for non-CSS scenarios.

Web server optimization

  • Enable Gzip compression on your Web server. Gzip compression can reduce file transfer sizes by up to 70%. ''Note:''' Gzip compression does not reduce the impact on end user cache sizes (cached uncompressed) so files sizes should be reduced as much as possible before Gzip compression.