Say, I've got an HTML file that I want to process using Javascript. For example:
span
or div
wrappers.­
entities.What would be the most efficient way to do this, i.e. I'd like to do it with a minimum amount of reflows.
The ideal case would be having the JS-code run before even the first layout. Is this possible? I know, it's generally a bad idea to execute expensive scripts before the page has been displayed for this would make the page look blank for some time and it's a really bad experience. However, I'm going to need this to work offline and this would not be an issue for my project.
Or, is there's a way to do all the dom modifications in one bunch, i.e. a reflow to be triggered after all the alterations have finished?
There are several ways. The primary goal with all of them is that you end up causing a single - or at least as few as possible - reflows/repaints.
Off-DOM element
You can work with elements without appending to the DOM, and then just append everything together once everything's set up.
The only issue with this is if your code needs to reference offset dimensions, since elements not yet in the DOM do not have any.
var container = document.createElement('section'); //not in the DOM yet
//do some extensive work here to prepare the doc
document.body.appendChild(container); //now we go to the DOM, causing a single re-paint
Doc fragment
A more formalised, and possible improved, variation on this theme would be document fragments, which bring a performance benefit (apparently). They're effectively a second, separate DOM that has no display.
String
Probably the quickest of all of these would be to build up your document as a string. The obvious implication is you can't use DOM methods on it, but if you're happy string-handling and REGEX'ing (not ideal on HTML, of course), could be worth considering.
Finally, if speed is of the essence and you have a LOT of computation or string-handling to do, you might want to harness web workers. These can't talk to the DOM directly, but you can outsource tasks to them and, crucially, they work asynchronously on a separate thread.
Remove the documentElement
from the document
, modify it and add it back to the document
.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>...</title>
</head>
<body>
<script type='text/javascript'>
var docElem = document.documentElement,
parentNode = docElem.parentNode,
nextSibling = docElem.nextSibling;
parentNode.removeChild(docElem); // reflow
// ...
docElem.lastChild.appendChild(docElem.ownerDocument.createElement('hr'));
// ...
parentNode.insertBefore(docElem, nextSibling); // reflow
</script>
</body>
</html>
This triggers two reflows and zero to two extra repaints.
jsFiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With