Skip to content

Instantly share code, notes, and snippets.

@developit
Last active August 23, 2023 21:26
Show Gist options
  • Save developit/90d94b2b92c8a2f466f2f44bca5d1cec to your computer and use it in GitHub Desktop.
Save developit/90d94b2b92c8a2f466f2f44bca5d1cec to your computer and use it in GitHub Desktop.
import { hydrate } from 'preact';
/**
* This method replaces your hydrate() call.
* Don't do this in production though, it's expensive.
*
* Before: hydrate(<App />, root);
* After: hydrateWithWarnings(<App />, root);
*/
function hydrateWithWarnings(vnode, parent) {
let observer = new MutationObserver(() => {});
observer.observe(parent, {
subtree: true,
childList: true,
attributes: true,
attributeOldValue: true
});
try {
hydrate(vnode, parent);
} finally {
const records = observer.takeRecords();
const roots = new Set();
const mismatches = [];
function isWithinChange(node) {
do {
if (roots.has(node)) return true;
} while (node = node.parentNode);
return false;
}
for (let mutation of records) {
let parent = mutation.target;
if (isWithinChange(parent)) continue;
if (mutation.attributeName) {
roots.add(parent);
let attribute = mutation.attributeName;
let value = parent.getAttribute(attribute);
mismatches.push({
reason: `Attribute "${attribute}" set to "${value}" (was "${mutation.oldValue}")`,
node: parent,
attribute
});
}
else {
for (let node of mutation.addedNodes) {
roots.add(node);
let name = node.localName ? `<${node.localName}> element` : `${node.nodeName} node`;
mismatches.push({
reason: `New ${name} appended to <${parent.localName}>`,
node,
parent
});
}
for (let node of mutation.removedNodes) {
roots.add(node);
let name = node.localName ? `<${node.localName}> element` : `${node.nodeName} node`;
mismatches.push({
reason: `${name} removed from <${parent.localName}>`,
node,
parent
});
}
}
}
observer.disconnect();
return mismatches;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment