Best practices of front end optimization

  sonic0002        2013-07-06 11:26:27       3,569        0    

1. Use DocumentFragment or innerHTML to replace complex elements insertion

DOM operation on browser is expensive. Although browser performance is improved much, multiple DOM elements insertion is still expensive and will affect the page load speed.

Assume we have an ul element on our page, we now want to retrieve a JSON list using AJAX and then update the ul using JavaScript. Usually we may write it as :

var list = document.querySelector('ul');  
ajaxResult.items.forEach(function(item) {  
  // Create element  
  var li = document.createElement('li');  
  li.innerHTML = item.text;  
  
  // Manipulate li such as change class,change attribute,add event listener etc  
  
  // Append to the list
  list.apppendChild(li);  
});  

Above code is actually ineffective, every time when the li is appended, the DOM tree of the page will be refreshed and rebuilt. Instead we should use DocumentFragment. DocumentFragment is the virtual storage of a group of child nodes and it has no parent element. In our example, we can imagine DocumentFragment as an ul element. The child nodes will be injected into the DOM only once as a whole.

var frag = document.createDocumentFragment();  
  
ajaxResult.items.forEach(function(item) {  
  // Create li  
  var li = document.createElement('li');  
  li.innerHTML = item.text;  
  
  // Manipulate li  such as change class, change attribute, add event listener etc 
  
  // Add li to the fragment
  frag.appendChild(li);  
});  
  
// Insert the fragment into the DOM
document.querySelector('ul').appendChild(frag);  

If you don't want to manipulate the DOM elements, you can directly insert HTML codes:

var htmlStr = ''; 
   
ajaxResult.items.forEach(function(item) {   
  htmlStr += '<li>' + item.text + '</li>'; 
}); 
   
document.querySelector('ul').innerHTML = htmlStr;

2. Handle frequent triggered event

Usually developers may add event listeners to UI elements when users need to interact with the page and these events may be triggered frequently such as window resize and mouseover events. When they are triggered, they would be triggered many times in a short period of time and callbacks will be called many times as well. We need to limit the number of executions.

// Get from UnderscoreJS  
function debounce(func, wait, immediate) {  
  var timeout;  
  return function() {  
    var context = this, args = arguments;  
    var later = function() {  
    timeout = null;  
    if (!immediate) func.apply(context, args);  
    };  
    var callNow = immediate && !timeout;  
    clearTimeout(timeout);  
    timeout = setTimeout(later, wait);  
    if (callNow) func.apply(context, args);  
  };  
  }  
  
// Add resize event listener,the callback will be executed every 300 milliseconds  
window.addEventListener('resize', debounce(function(event) {  
  
  // DO SOMETHING 
  
}, 300));  

debounce will return a function, this function will contain your callback function. The execution frequency can be limited.

3. Use Array.prototype.join to do string concatenation

Usually we concatenate strings using + operator, we can use Array.prototype.join as well.

For example:

htmlStr += '<li>' + item.text + '</li>';

With Array.prototype.join:

var items = []; 
   
ajaxResult.items.forEach(function(item) { 
  items.push('<li>', item.text, '</li>'); 
}); 
   
document.querySelector('ul').innerHTML = items.join('');

4. Store static content

Web Storage API has a big improvement compared to Cookie API and it's sued by developers for many years. We can use it to store static content such as sidebar menus or contents loaded with AJAX.

define(function() {  
  
  var cacheObj = window.sessionStorage || {  
    getItem: function(key) {  
    return this[key];  
    },  
    setItem: function(key, value) {  
    this[key] = value;  
    }  
  };  
  
  return {  
    get: function(key) {  
    return this.isFresh(key);  
    },  
    set: function(key, value, minutes) {  
    var expDate = new Date();  
    expDate.setMinutes(expDate.getMinutes() + (minutes || 0));  
  
    try {  
      cacheObj.setItem(key, JSON.stringify({  
        value: value,  
        expires: expDate.getTime()  
      }));  
    }  
    catch(e) { }  
    },  
    isFresh: function(key) {  
    var item;  
    try {  
      item = JSON.parse(cacheObj.getItem(key));  
    }  
    catch(e) {}  
    if(!item) return false;  
  
    return new Date().getTime() > item.expires ? false : item.value;  
    }  
  }  
});  

This tool provides some get and set methods, it's very simple to call these methods:

require(['storage'], function(storage) {  
  var content = storage.get('sidebarContent');  
  if(!content) {  
    // Do an AJAX request to get the sidebar content  
  
    // ... and then store returned content for an hour  
    storage.set('sidebarContent', content, 60);  
  }  
});

The same content will not be loaded again. Go back and check your design and find out those content which are static and use Web Storage to store them.

5. Use CSS animation

Web design now needs large number of animations, jQuery, MooTools can help on this. Although browsers now support animation made with transformation and keyframe, many people are still using JavaScript to create animation effect. In fact using CSS is more efficient than JavaScript on creating animation and it needs less codes as well. Many CSS animations are processed by GPU, so the animation can play smoothly. You can use below codes to enforce hardware acceleration.

.myAnimation {  
  animation: someAnimation 1s;  
  transform: translate3d(0, 0, 0); 
}  

If the browser doesn't support CSS animation(IE 8 and below), you can include JavaScript animation:

6. Use event delegation

Assume you have a list of links in an

    element, and you want to trigger a click event on each link, you may want to add event listener to each link,but this method is inefficient. Instead we can use event delegation in JavaScript, since event is bubbling, we just need to add an click event to the parent ul element and we then check which link is clicked in the event handler.
document.querySelector('#parent-list').addEventListener('click', function(e) {  
  // e.target is the element being clicked 
  // Check whether the target is a li element
  if(e.target && e.target.tagName == 'LI') {  
    // Check which li element clicked and do something accordingly  
  }  
});

7. Use Data URI  to replace image src

To improve page load speed, we can do more beyond compressing codes. Reducing the request number to the server is also a considerable option. One way to reduce request number is to use Data URI to replace image src

<!-- Original method --> 
<img src="/images/logo.png" /> 
   
<!-- Use data URI --> 
<img src="data: image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8fHx8fHx8fHx8fHx8fH ...." /> 
   
<-- Example:  http://davidwalsh.name/demo/data-uri-php.php -->

The page size will increase a bit, but it reduces the numbers of request sent to the server. Most of browsers are now supporting Data URI, you can use Data URI to load background image as well in CSS.

There are many more optimization tips to come...

Source : http://www.gbtags.com/gb/tag/usertag/5929.htm

JAVASCRIPT  TIPS  OPTIMIZATION  FRONT END 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Password will expire in 400 days