Skip to content

Instantly share code, notes, and snippets.

@JamesIves
Last active March 14, 2024 13:24
Show Gist options
  • Save JamesIves/b05f77a6e4f215dd37cd9425769c4dad to your computer and use it in GitHub Desktop.
Save JamesIves/b05f77a6e4f215dd37cd9425769c4dad to your computer and use it in GitHub Desktop.
Walks the DOM and creates a table based on how many elements it occurs in the light and shadow DOM, along with a combined total separated by a coloured header. Useful for tracking down performance issues with excessive DOM nodes. Can be run in the browser dev tools console.
/**
* Walk the DOM tree and tally the number of elements between light and shadow dom.
*/
function walkDOM(root, nodeCounts = {}, shadowNodeCounts = {}, isShadow = false) {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
const nodes = [];
const excludedNodes = ['META', 'SCRIPT', '#text']; // Add any other node types you want to exclude
while(walker.nextNode()) {
if (!excludedNodes.includes(walker.currentNode.nodeName)) {
nodes.push(walker.currentNode);
const counts = isShadow ? shadowNodeCounts : nodeCounts;
counts[walker.currentNode.nodeName] = (counts[walker.currentNode.nodeName] || 0) + 1;
}
if (walker.currentNode.shadowRoot) {
const shadowResult = walkDOM(walker.currentNode.shadowRoot, nodeCounts, shadowNodeCounts, true);
nodes.push(...shadowResult.nodes);
}
}
return { nodes, nodeCounts, shadowNodeCounts };
}
function findMostEncounteredNodes(nodeCounts, label, color) {
// Convert the nodeCounts object to an array of [node, count] pairs
const nodeCountPairs = Object.entries(nodeCounts);
// Sort the array by count in descending order
nodeCountPairs.sort((a, b) => b[1] - a[1]);
// Log all node types with colored header
console.log(`%cNodes in ${label}:`, `color: ${color}`);
console.table(nodeCountPairs);
}
const { nodes, nodeCounts, shadowNodeCounts } = walkDOM(document);
findMostEncounteredNodes(nodeCounts, 'light DOM', 'blue');
findMostEncounteredNodes(shadowNodeCounts, 'shadow DOM', 'green');
// Combine light and shadow DOM counts
const combinedCounts = { ...nodeCounts };
for (const node in shadowNodeCounts) {
combinedCounts[node] = (combinedCounts[node] || 0) + shadowNodeCounts[node];
}
findMostEncounteredNodes(combinedCounts, 'combined light and shadow DOM', 'red');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment