microsite
Version:
<br /> <br />
166 lines (165 loc) • 5.6 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { h, hydrate as rehydrate, render } from "preact";
const win = window;
if (!("requestIdleCallback" in window)) {
win.requestIdleCallback = function (cb) {
return setTimeout(function () {
var start = Date.now();
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
},
});
}, 1);
};
win.cancelIdleCallback = function (id) {
clearTimeout(id);
};
}
const createObserver = (hydrate) => {
if (!("IntersectionObserver" in window))
return null;
const io = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
const isIntersecting = entry.isIntersecting || entry.intersectionRatio > 0;
if (!isIntersecting)
return;
hydrate();
io.disconnect();
});
});
return io;
};
function attach(fragment, data, { name, source }, cb) {
const _a = data.p, _b = _a === void 0 ? {} : _a, { children = null } = _b, props = __rest(_b, ["children"]), { m: method = "idle", f: flush } = data;
const hydrate = async () => {
if (win.__MICROSITE_DEBUG)
console.log(`[Hydrate] <${name} /> hydrated via "${method}"`);
const { [name]: Component } = await import(source);
if (flush) {
render(h(Component, props, children), fragment);
}
else {
rehydrate(h(Component, props, children), fragment);
}
if (cb)
cb();
};
switch (method) {
case "idle": {
if (!("requestAnimationFrame" in window))
return setTimeout(hydrate, 0);
win.requestIdleCallback(() => {
requestAnimationFrame(hydrate);
}, { timeout: 500 });
break;
}
case "visible": {
if (!("IntersectionObserver" in window))
return hydrate();
const observer = createObserver(hydrate);
const childElements = fragment.childNodes.filter((node) => node.nodeType === node.ELEMENT_NODE);
for (const child of childElements) {
observer.observe(child);
}
break;
}
}
}
function createPersistentFragment(parentNode, childNodes) {
const last = childNodes && childNodes[childNodes.length - 1].nextSibling;
function insert(child, before) {
try {
parentNode.insertBefore(child, before || last);
}
catch (e) { }
}
return {
parentNode,
firstChild: childNodes[0],
childNodes,
appendChild: insert,
insertBefore: insert,
removeChild(child) {
parentNode.removeChild(child);
},
};
}
const ATTR_REGEX = /(:?\w+)=([^\s]*)/g;
function parseHydrateBoundary(node) {
if (!node.textContent)
return {};
const text = node.textContent.slice("?h ".length, -1);
let props = {};
let result = ATTR_REGEX.exec(text);
while (result) {
let [, attr, val] = result;
if (attr === "p") {
props[attr] = JSON.parse(atob(val));
}
else {
props[attr] = val;
}
result = ATTR_REGEX.exec(text);
}
return props;
}
function findHydrationPoints() {
const nodeIterator = document.createNodeIterator(document.documentElement, NodeFilter.SHOW_COMMENT, {
acceptNode(node) {
if (node.textContent && node.textContent.startsWith("?h c"))
return NodeFilter.FILTER_ACCEPT;
return NodeFilter.FILTER_REJECT;
},
});
const toHydrate = [];
while (nodeIterator.nextNode()) {
const start = nodeIterator.referenceNode;
const data = parseHydrateBoundary(start);
const childNodes = [];
let end = start.nextSibling;
while (end) {
if (end.nodeType === end.COMMENT_NODE &&
end.textContent &&
end.textContent.startsWith("?h p")) {
Object.assign(data, parseHydrateBoundary(end));
break;
}
childNodes.push(end);
end = end.nextSibling;
}
toHydrate.push([
createPersistentFragment(start.parentNode, childNodes),
data,
[start, end],
]);
}
return toHydrate;
}
export default (manifest) => {
const init = () => {
const $cmps = findHydrationPoints();
for (const [fragment, data, markers] of $cmps) {
const { c: key } = data;
const [name, source] = manifest[key];
if (name && source) {
attach(fragment, data, { name, source }, () => {
fragment.childNodes.forEach((child) => child.tagName === "HYDRATE-PLACEHOLDER" ? child.remove() : null);
markers.forEach((marker) => marker.remove());
});
}
}
};
win.requestIdleCallback(init, { timeout: 1000 });
};