Skip to content

Reuse DOM nodes / state across components? #1411

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

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

Reuse DOM nodes / state across components? #1411

nolanlawson opened this issue May 3, 2018 · 3 comments

Comments

@nolanlawson
Copy link
Contributor

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
Copy link
Member

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants