UI Change Detection and Rendering Algorithms
A deep dive into UI change detection algorithms and how they work
Disclaimer: this is an on-going article and needs some refining
Software Engineering for user interfaces has never been more complex. Due to the explosion of the Web, UI's are now heavily dynamic, non-deterministic pieces of software that end-users directly use, making bugs more likely to be found and performance issues arguably more visible than other areas of software engineering. Understanding concepts such as change detection are often overlooked (in my opinion) due to the fact that they are merely under the hood details of what modern UI frameworks give developers, such as React, Angular, Vue and Svelte, to name a few. Honestly speaking, this article (or series of articles...I'm still deciding) is more for me than for you. It's simply a place for me to organise my thoughts with the benefit of having to be all the more thorough due to the audience of the internet. Before we get into it, here is a quote that I tend to think of when doing a deep dive into a subject such as this:
“The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.”
— Donald Knuth
With this in mind, why bother looking into this? My personal answer is because it helps me to understand what to focus on so that I avoid prematurely optimising. For example, when writing an application at work, if I don't the framework I am using, then I will likely make incorrect assumptions about how much I need (or do not need to) optimise my code. By understanding how it works, I can use the framework to do the heavy lifting, so that I can focus on writing business logic - what my employer cares more about than my potentially unnecessary optimisations.
Angular - Incremental DOM
Angular's change detection mechanism is based on an idea called "Incremental DOM", which, in short, is a UI rendering approach that incrementally updates the DOM tree as opposed to creating virtual copies of the DOM and diffing them based on the before and after state of changes, i.e. the Virtual DOM approach, which we will cover in the next section. It performs these updates by taking the developer's Angular components and compiling them into a set of instructions of where to render the component and any data that needs to be updated. Google has a Github repo called incremental-dom
which describes itself as "An in-place DOM diffing library" which is a helpful description. Though Angular doesn't use this library directly, the core implementation is similar.
Let's look at an example in a non-angular context:
If you want to run this code, simply npm i incremental-dom
(i'm using TypeScript for my example).
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bind it</title>
</head>
<body>
<div id="incremental-dom-container"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
var container = document.getElementById('incremental-dom-container');
var elementOpen = IncrementalDOM.elementOpen,
elementClose = IncrementalDOM.elementClose,
text = IncrementalDOM.text;
function render(data: { text: any; someCondition: any }) {
elementOpen('div', '');
if (data.someCondition) {
text(data.text);
}
elementClose('div');
}
var data = {
text: 'Hello World!',
someCondition: true
};
IncrementalDOM.patch(container!, () => render(data));
data.text = 'Updated Hello World!';
setTimeout(() => IncrementalDOM.patch(container!, () => render(data)), 1000);
What is happening?
It's very simple, we are creating a DOM node programmatically, then rendering it into a container element in the HTML. We then use a setTimeout
method to update this element after 1 second.
Updates DOM
Now let's look at an Angular example:
When designing Angular's new rendering pipeline 'Ivy', the Angular team wanted to focus on performance for the mobile platform, where memory is more constrained than desktop applications [1]. The incremental DOM approach requires less memory than the more popular Virtual DOM approach, as it increments a single tree and doesn't have to manage reconciling the changes between nodes in different trees.
Next is part 2...
Subscribe to my newsletter
Read articles from Jamie Burton directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jamie Burton
Jamie Burton
Software Engineer from London, with a love for browser internals, QoS, HTTP and UI engineering.