DEV Community

Cover image for HTML strings vs the DOM API: from a small benchmark to a surprising result
Dario Mannu
Dario Mannu

Posted on

HTML strings vs the DOM API: from a small benchmark to a surprising result

Which of the following do you think is faster?

  1. direct DOM API calls (createElement, appendChild)
  2. assigning HTML strings to innerHTML

Chances are you'll say the former is faster and most people would agree.
This belief is so deeply rooted in popular culture that even many framework authors chose to base their entire architecture around DOM API calls.

Now, critical thinking to the rescue. Is this really, really true?

At the end of the day, browsers have been optimised around parsing HTML for decades and writing HTML feels better than the raw DOM API, so... true or not, is is worth it at all?


Thought it's time to test assumptions and hypotheses, both in extreme and more realistic scenarios. An extreme scenario is one where you render a view tens of thousands of times on a page. In a realistic scenario, you render a view once.

The setup

Two simple functions on the scene. One builds the view by hand with createElement, setAttribute, appendChild, the other generates the same structure with a single HTML template string.

// DOM API version (shortened)
const domFn = () => {
  const container = document.createElement('div');
  target.appendChild(container);
};

// HTML template version (shortened)
const htmlFn = () => {
  target.innerHTML = `
    <div>
      <header><h1>Dashboard</h1></header>
    </div>
  `;
};
Enter fullscreen mode Exit fullscreen mode

Next, rinse and repeat. Render 1, 2, 4, 8, up to 1024 times.

First-run: surprise surprise!

Before we get to which method is faster when we render many, many times, here is the shocking part: if you only set innerHTML once, it's nearly always faster than building the DOM structure one createElement at a time!

It's not just an opinion, it's hard numbers in various scenarios.

  1. a very simple HTML structure
  2. a more articulated one

These links run on Stackblitz and show slighly different values than a local build. Feel free to download these projects and run the code yourself. The difference will be even more apparent on local.

Before you get too excited, look at the numbers, though. We're still talking less than 1ms difference, which is totally negligible for an end user.

This probably happens because HTML parsing is one of the most well optimised code paths in the browser. Turning a string into DOM nodes is fast. Meanwhile the DOM API version makes many small JavaScript calls before the engine has had time to optimise the function.

So for the first render the HTML version comes out ahead.

After that everything flips

As soon as the test repeats the operation more than once, the DOM API becomes faster.

This is where the JavaScript engine steps in. Once the DOM-building function has run a couple of times the engine fully optimises it. The series of createElement and appendChild calls becomes predictable and efficient.

The HTML version cannot use the same advantage. It always has to parse the whole template again. So from two runs onwards the DOM API pulls ahead and keeps widening the gap as the number of runs increases.

The same pattern shows up locally and on StackBlitz. The exact numbers shift, but the behaviour is identical.

What this means in practice

HTML strings are not slow. Quite the opposite. Browsers can parse a view so quickly that the first render can match or beat manual DOM calls. This is useful because typical applications build a view once, not hundreds of times in a loop.

For repeated updates or very frequent re-renders the DOM API becomes the better choice. Once the engine optimises the function it avoids parsing costs and becomes more stable.

In most real apps the difference is small enough that the choice comes down to clarity. If a view is easier to express as a template string, it is a perfectly reasonable approach. You are not paying a penalty for using it.


Learn More

Top comments (0)