Rather than creating and diffing a fine-grained tree of elements every render, it's very easy to use the syntactic structure of a template to see exactly what parts can and cannot change. To get stable and minimal DOM updates you just compare the template identity to the previously rendered template - if they match you update the dynamic expressions, if they don't you clear and render the new template.
This is what we did with lit-html and it's quite a bit faster (and smaller) than React and doesn't require a compiler because it uses standard JS tagged template literals. https://lit.dev/docs/libraries/standalone-templates/
It's a very simple approach and very, very hard to beat in the fast/small/simple/buildless tradeoff space. I hope one day that the DOM can include standard updatable DOM with a technique like this on top of the template instantiation proposal from Apple. It's such a common need that it should be built in.