-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
This may not have an easy solution, but I wanted to document this tricky performance problem I ran into.
If you follow the sapper-template, you end up with multiple pages each containing a Layout and a Nav. When you navigate from one page to another, this Nav
remains ~99% the same, and yet Svelte will tear down the entire DOM tree and recreate the DOM structure from scratch.
This has a few undesirable performance impacts:
- A delay caused by destroying and re-creating largely identical DOM nodes
- Style and layout must be recalculated, even though the DOM structures are largely the same
- For "perceived performance," it would be nice to run animations on the Nav during this transition, but it's impossible to animate the old DOM nodes since they get destroyed. So you instead have to wait for the new DOM nodes to be inserted and then animate those, which leads to a slight delay between the click and the start of the animation. (See the animations in pinafore.social when clicking on the nav buttons for an example.)
I'm not sure there's an easy solution to this, but maybe something like the following would be possible?
<!-- Nav.html -->
<script>
const nodePool = []
export default {
recycleNode (node) {
nodePool.push(node)
},
updateNode (node) (
// any work to update the component with the existing node
},
getRecycledNode () {
return nodePool.pop() // null/undefined indicates Svelte should create a new one
}
}
</script>
See this infinite list implementation for where I got some of these ideas about recycling. It's also possible it would be better to recycle the components themselves (including state) rather than just the DOM nodes, but this is just a sketch.