New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse DOM nodes / state across components? #1411

Closed
nolanlawson opened this Issue May 3, 2018 · 3 comments

Comments

Projects
None yet
2 participants
@nolanlawson
Copy link
Contributor

nolanlawson commented May 3, 2018

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:

  1. A delay caused by destroying and re-creating largely identical DOM nodes
  2. Style and layout must be recalculated, even though the DOM structures are largely the same
  3. 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.

@Rich-Harris

This comment has been minimized.

Copy link
Member

Rich-Harris commented May 3, 2018

It doesn't have an easy solution, but it is absolutely something we need to figure out. My concern is more for the perceived performance aspects than anything — I want it to be as easy to do this sort of thing as it is to make pages without transitions.

One possible approach would be something like this: sveltejs/sapper#157. But it might not be sufficiently general. Definitely going to think on this.

@nolanlawson

This comment has been minimized.

Copy link
Contributor

nolanlawson commented May 3, 2018

Yes, sveltejs/sapper#157 does look like it would solve the immediate problem, but I agree it'd be nice to have a more generic solution. Sometimes it's useful to reuse DOM nodes across a variety of scenarios, e.g. for items in a virtual list. (This is another case where I am currently just destroying and recreating DOM nodes.)

@nolanlawson

This comment has been minimized.

Copy link
Contributor

nolanlawson commented Jun 20, 2018

Looks like this is largely fixed by sveltejs/sapper#157 (comment). I still think it'd be nice to have a generic way to reuse DOM nodes (e.g. for the virtual list scenario), but this definitely unblocks my main gripe. Time for me to upgrade Sapper! 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment