Web API: appendChild V.S. createDocumentFragment

All the JavaScript rendering libraries and frameworks we use, all boils down to the fundamental web APIs at the end of the day. People are so used to work with the high-level React APIs or Vue syntaxes (me included), we forget the raw and interesting layer underneath it all. But not today!

Today I'm going to show you something that you'll probably never use again in your life as a JavaScript developer, something that will not earn you any new titles. All I can say is that it is interesting and it is fun!

Now let's get straight into it.

How does the DOM work?

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the page so that programs can change the document structure, style, and content. The DOM represents the document as nodes and objects. That way, programming languages can connect to the page. - MDN

Everything that the user sees or doesn't see all exist on the DOM, to add or remove something new on to the DOM we can do something like this:

// create node
const node = document.createElement('div');
// append node to DOM
document.body.appendChild(node);

This is easy enough, but what about createDocumentFragment?

MDN documentation says that createDocumentFragment API (most likely) has better performance than appendChild API. Since a document fragment only exists in memory and is not part of the main DOM tree. This means appending children to it does not cause page reflow, thus gives better performance.

So how much more performant are we talking about here? 10%, 20% or like 100%?! Let's do some experiments.

const totalNumOfNodes = 100000;

const parent = document.createElement("div");
document.body.appendChild(parent);

const t0 = performance.now();

for (let i = 0; i < totalNumOfNodes; i++) {
  const child = document.createElement("div");
  child.textContent = `test 1 - ${i}`;
  parent.appendChild(child);
}

const t1 = performance.now();

const fragments = document.createDocumentFragment();

for (let i = 0; i < totalNumOfNodes; i++) {
  const child = document.createElement("div");
  fragments.appendChild(child);
}
parent.appendChild(fragments);

const t2 = performance.now();

console.log("Rendering took " + (t1 - t0) + " milliseconds.");
console.log("Rendering took " + (t2 - t1) + " milliseconds.");
Edit createDocumentFragment v.s. appendchild Performance

The results are shown in the graph below, I didn't want to try with even more nodes but it is easy to see the more nodes we add the more advantage createDocumentFragment will have.

Screenshot 2019-04-17 at 00.12.40

Final words

I haven't checked what the popular rendering libraries or frameworks are doing to optimise the addition of a massive number of nodes. But I can't imagine createDocumentFragment isn't utilised to improve performance since people do care and research which has the best performance.

Learning about createDocumentFragment is probably not a very practical piece of knowledge. Most of us would never come across opportunities where this becomes an issue, but hey, if this comes up in an interview you will nail it!