Skip to content

Instantly share code, notes, and snippets.

@developit
Created September 24, 2021 16:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save developit/6f2666740a1b4925f1d15ea2894f28ec to your computer and use it in GitHub Desktop.
Save developit/6f2666740a1b4925f1d15ea2894f28ec to your computer and use it in GitHub Desktop.
import { h, hydrate } from 'preact';
let C = 0;
export function Root({ href, data, children }) {
let json = data && JSON.stringify(data);
let id = 'root:'+++C;
return [
h(`!--${id}--`),
children,
h('component-root', { href, id },
json && h('script', { type: 'text/props' }, json)
)
];
}
if (typeof customElements !== 'undefined') {
customElements.define('component-root', class extends HTMLElement {
connectedCallback() {
let id = this.getAttribute('id');
// hydrate any serialized props/data:
try {
var data = JSON.parse(this.firstElementChild.textContent)
} catch (e) {}
// walk back to the comment marker to collect owned root nodes:
let childNodes = [], child = this, p = this.parentNode;
while ((child = child.previousSibling)) {
if (child.nodeType !== 8) childNodes.unshift(child);
else if (child.data === id) break;
}
// create a fake DOM root housing only owned root nodes:
let frag = {
childNodes,
removeChild: c => p.removeChild(c),
appendChild: c => p.insertBefore(c, this),
insertBefore: (c, i) => p.insertBefore(c, i || this)
};
// import the component, then hydrate its DOM subtree:
let [url, exportName] = this.getAttribute('href').split('#');
import(url).then(m => {
let component = m[exportName] || m.default;
hydrate(h(component, data), frag);
});
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment