4 ms·
I'm experimenting with recreating the whole DOM tree like this: function render() { restoreFocus(() => document.body.replaceChildren(App())) }
by efortis 9mo ago
I'm experimenting with recreating the whole DOM tree like this:
function render() {
restoreFocus(() =>
document.body.replaceChildren(App()))
}
function App() {
return (
createElement('div', { className: 'App' },
createElement('h1', null, 'Hello, World')))
}
function createElement(tag, props, ...children) {
const elem = document.createElement(tag)
for (const [k, v] of Object.entries(props || {}))
if (k === 'ref') v.elem = elem
else if (k === 'style') Object.assign(elem.style, v)
else if (k.startsWith('on')) elem.addEventListener(k.slice(2).toLowerCase(), ...[v].flat())
else if (k in elem) elem[k] = v
else elem.setAttribute(k, v)
elem.append(...children.flat().filter(Boolean))
return elem
}
`restoreFocus` is here:
https://github.com/ericfortis/mockaton/blob/main/src/client/dom-utils.js#L51 https://github.com/ericfortis/mockaton/blob/main/src/client/...
Results so far:
Rendering the whole DOM tree (instead of VDOMs) is a fast process. The slow part is attaching (committing) elements to the doc. For example, I have a test of 20,000 elements which takes <30ms to render, while attaching them takes 120ms.
Since the performance is mainly bound to the commit phase, with a DOM merging library, or hopefully, if we get a native API such as `document.replaceChildren(...App(), { merge: true })`, this approach could be better.
Caveats:
Although it restores focus, that's not the only thing we need to preserve, we also need to preserve scroll position and cursor position.
So to work around that, I still have to step out fully declarative, by just replacing the part that changed. For example, here I had to do manually mutate the DOM:
https://github.com/ericfortis/mockaton/blob/main/src/client/app.js#L380 https://github.com/ericfortis/mockaton/blob/main/src/client/...
- my_throwaway23 9mo agoLooks an awful lot like https://github.com/jorgebucaran/hyperapp https://github.com/jorgebucaran/hyperapp
- efortis 9mo agoBoth are based on the signature of React.createElement. JSX gets compiled to something like that. https://react.dev/reference/react/createElement https://react.dev/reference/react/createElement