domenic / template-parts

Brainstorming a <template> parts proposal
20 stars 0 forks source link

performance considerations #4

Open trusktr opened 2 years ago

trusktr commented 2 years ago

The DOM is inherently a fine-grained system: we update exactly what we need to update, then the HTML engine re-renders.

Can we adopt fine grained reactivity in the template API by default? Could it be possible to use Proxies to give people an API that is easy to use with O(1) instead of O(n) overhead?

const [dom, data] = template.instantiate(
  {x: 123, y: 456},
  // Template.defaultProcessor // second parameter defaults to this
)

// data is a Proxy wrapping the input object.

// Modifying a DocumentFragment but not live DOM over and over is indeed useless, and stamping it out over and over would be expensive, so this API example manipulates live DOM (somehow)

// dom is, perhaps, some new type of fragment that tracks the DOM it inserts? idk
document.body.append(dom)

data.x = 456
data.y = 789

// Updates are batched, so this updates the template in the future (a microtask perhaps?)

setTimeout(() => {
  data.y = 246 // updates only one part of the DOM, fine-grained, no diffing
}, 1000)

If we don't nail down performance, people are gonna be using Solid, React, Svelte, etc, rather than this. We need to get this right.

Maybe my idea isn't the best, but I hope we can think about performance because so far the proposal doesn't really seem to be.

keithamus commented 2 years ago

I think this can be an implementation detail for libraries. The "Parts" are given to the processor and act as the reactive primitives I think you're after. It's then down to libraries to create intermediary objects between what they pass to createInstance and how they can model reactivity from data to "Parts".

dy commented 2 years ago

I experimented with that data approach in templize. Generally update(obj) does not necessarily take new object each time - that is processor specific implementation. And in fact that can be more performant, since data.x = y would require update on each assignment or some async throttling mechanism. Also proxy/setter is slower than simple object that can be represented as struct in vm.