Skip to content

Instantly share code, notes, and snippets.

@matthewharwood
Last active June 14, 2020 20:45
Show Gist options
  • Save matthewharwood/fa8a92413f0f52c68f9f9eba9e62027f to your computer and use it in GitHub Desktop.
Save matthewharwood/fa8a92413f0f52c68f9f9eba9e62027f to your computer and use it in GitHub Desktop.
// hydrate.js
function autoHydrate(Component, name) {
if (isClient) {
return Component;
}
return props => html`
<component-root name=${name} />
<${Component} ...${props} />
<script
type="text/hydration"
dangerouslySetInnerHTML=${{
__html: JSON.stringify({ props })
}}
/>
`;
}
// componentMap.js
import {autoHydrate} from './hydrate.js';
const COMPONENT_MAP = {
Foo: () => import('./foo'),
Baz: () => import ('./baz'),
Bar: () => import('./bar'),
};
const Chunk = {};
for (let i in COMPONENT_MAP) {
Chunk[i] = autoHydrate(COMPONENT_MAP[i], i);
}
export {Chunk};
// page-map.js
const COMPONENT_MAP = {
{route: '/', components: [Foo],
{route: '/about', components: [Foo, Baz],
{route: '/work', components: [Foo,Bar],
{route: '/lab', components: [Foo,Baz, Bar],
}
// main.js
import { h, hydrate, render } from "preact";
import {AH} from './components/component-map';
import {whenVisible} from '../utils/when_visible';
class ComponentRoot extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
const childNodes = [];
let $end = this;
let data = {};
whenVisible(this, () => {
while (($end = $end.nextSibling)) {
if (
$end.nodeName === "SCRIPT" &&
$end.getAttribute("type") === "text/hydration"
) {
try {
data = JSON.parse($end.textContent) || {};
} catch (e) {}
break;
}
childNodes.push($end);
}
this.root = {
childNodes,
appendChild: c => this.parentNode.insertBefore(c, $end)
};
Promise.resolve()
.then(() => Chunk[this.getAttribute("name")])
.then(Component => {
hydrate(h(Component, data.props), this.root);
});
});
}
disconnectedCallback() {
render(null, this.root);
}
}
customElements.define("component-root", ComponentRoot);
// index.html
<html>
<body>
<script src="main.js"></script>
<script src="foo.js"></script>
</body>
</html>
// work.html
<html>
<body>
<script src="main.js"></script>
<script src="foo.js"></script>
<script src="bar.js"></script>
</body>
</html>
// about.html
<html>
<body>
<script src="main.js"></script>
<script src="foo.js"></script>
<script src="baz.js"></script>
</body>
</html>
// lab.html
<html>
<body>
<script src="main.js"></script>
<script src="foo.js"></script>
<script src="baz.js"></script>
<script src="bar.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment