Quick Tip – Too Much DOM Manipulations Can Hurt You

March 28, 2013

no comments

Quick Tip – Too Much DOM Manipulations Can Hurt You

Lately, I had a few consulting sessions for customers about JavaScript performance. One of the things that repeated in all of the apps I saw was the misunderstanding of too much Document Object Model (DOM) manipulations implications on app performance. There are a lot of good articles about the subject and this post will only cover one method to increase JavaScript performance. The scenario is based on a code I saw at a customer.

DOM Manipulations and Reflows

When we build web apps, we use JavaScript to manipulate the DOM and to update the web pages we build. One of the things that we should be aware of is browser reflows. Reflow is a browser process which determines how the page should be displayed to the user. Every single DOM manipulation (for example changes in CSS or adding/updating/removing elements) can trigger a reflow. Reflows can take some time and affect the performance of your web page. A lot of reflows can decrease the app performance and make it sluggish and slow. 

The Customer’s Problem

In the customer scenario they needed to create a big DOM part according to some data they received from the server. The problem was that they made changes to the DOM for each element that they got. Since we are talking about adding and manipulating a lot of elements the performance of the app was really bad. The first thing I did was to open Chrome developer tools and to capture their app in the Timeline. What I saw was that a lot of app time was spent on rendering and painting. Then, I asked the developer to show me the code that create the DOM part and saw that he created the new DOM part using jQuery each function and appending the created elements straight into the DOM in each iteration. Here is a simple example of such operation without using jQuery each function:

function addElements(element) {
    var div;
    for (var i = 0; i < 5; i++) {
        div = document.createElement('div');
        div.textContent = 'added';
        element.appendChild(div);
    }
}

In the example, five div elements are added to a given element. In each iteration a reflow process might be triggered due to changes in the DOM and cause a decrease in the performance.

Suggested Solution

A way to solve the previous problem is using a document fragment and appending it to the DOM. All the document fragment’s elements will be appended to the supplied element and we will have only one reflow. Here is the fixed code block:

function addElementsBetter(element) {
    var div,
        fragment = document.createDocumentFragment();
    for (var i = 0; i < 5; i++) {
        div = document.createElement('div');
        div.textContent = 'added';
        fragment.appendChild(div);
    }
    element.appendChild(fragment);
}

As you can see, I’m using the document.createDocumentFragment function to create a DocumentFragment element. Then, I’m appending all the created divs to that element. After the loop’s end I’m appending the fragment to the element.

Summary

After fixing the problem we managed to decrease the performance of the app by ~50%. The app’s code is doing all the manipulations in memory and only in the end the change is appended to the DOM. Understanding what can cause performance problems can help you avoid those problems in the future.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>