When you replace parts of the DOM with new HTML, using .innerHTML = newHtml is usually the simplest and fastest option. It comes at the price of your DOM elements losing state, like input values, scroll position, progress in a video player, or even more complex state for custom elements.
One option to avoid this are libraries like morphdom Show archive.org snapshot (as used by Phoenix Liveviews) or idiomorph Show archive.org snapshot (as used by Rails' Turbo).
It lets you write
morphdom(node, newHtml)
or
Idiomorph.morph(node, newHtml)
which will try to do the minimum DOM changes required to arrive at the target HTML. Idiomorph seems to be a bit smarter when your DOM structure changes, and you can help both libraries by providing id attributes.
There are a few configuration options to allow skipping parts of the DOM tree, for example to avoid throwing away changes.
Both libraries weigh in at around 10kB uncompressed.
Take care when using Unpoly
This does not play nice with Unpoly by default, since compilers are neither properly initialized nor destructed in the morphed DOM.