JavaScript on Modern Web

JavaScriptly



LightningDOM to Balance DOM vs innerHTML

Using DOM API versus innerHTML to create/change content on webpage has been in discussion for years. The pain (slow DOM manipulation speed) left by Internet Explorer causes a big concern over DOM API for serious use in practice because the browser is still holding big slice of market share today (about 80%).

We can guess that the browser war (re)started by Firefox and stirred up by Google Chrome lately will result in better IE versions, yet that bright day won’t come any time soon.

Recently, I had reviews on PURE and Chain.js as client-side template engines. Though both libraries take pure, unobtrusive JavaScript approach for implementation, PURE seems more eager about speed when using innerHTML to create elements while Chain.js depends on DOM API for more flexible and direct manipulation.

I cannot say what approach is better. PURE may have some advantage on page with huge number of DOM elements to be created/changed but I think most of projects will be happy with Chain.js for its power. It grows a question: any chance that we can achieve both flexibility and speed in these libs? Probably, LightningDOM donated by Peter Rust will be a right answer.

In the post, Peter places LightningDOM as “a layer between the raw HTML and your templating/data-mapping code, without the slowness of the DOM.” So how it works? Just see the example.

1
2
3
4
var strMarkup = document.getElementById('destination').innerHTML;
var dom = new LightningDOM(strMarkup);
dom.firstChild().innerText("I Love speed!");
document.getElementById('destination').innerHTML = dom.outerHTML();

Not too difficult to understand, right? You give all HTML markups to LightningDOM, do anything you want with familiar getters/setters like you can do with DOM API then assign the result back to real DOM’s innerHTML.

Peter tells more about internal implementation to get both speed and lightness in the library.

The LightningDOM parses the given HTML using Regexes. I have two different parse algorithms (but both using the same regex). IE is much faster at parsing the whole markup by doing a single regex replace to convert the markup into JSON and then to eval the JSON. FF (and I’m guessing Chrome & Opera) is much faster at looping through the markup with a global regex.

All the tags are parsed into a two-dimensional array (well, technically an array of arrays), which represents all the information in the tags. Here’s a pretty look at the internal data structure representing a chunk of HMTL (note that we use a simpler object model inspired by ElementTree to representing the inner-text as a “tail” of the previous tag, rather than a nested “Text Node”).

Array of Arrays (_aMarkup):

Of course, the decision to utilize LightningDOM for PURE or Chain.js depends on leaders of projects but it does not prevent you from taking advantage of the lib if you see true value from it. Personally, I think it’s a good solution though I’ll have more tests/benchmarks to evaluate its stability across browsers.