UNPKG

@skatejs/ssr

Version:

Server-side render your web components.

77 lines (63 loc) 2.34 kB
const { minify } = require('uglify-es'); const cache = {}; // Rehydrates the host element with a shadow root. function rehydrate() { var script = document.currentScript; var fakeShadowRoot = script.parentNode; var host = fakeShadowRoot.parentNode; var move = function(from, to) { while (from && from.firstChild) { to.appendChild(from.firstChild); } }; // This cleans up the resulting DOM but also seems to have a positive impact on performance. fakeShadowRoot.removeChild(script); // First thing we do is remove the fake shadow root so we can attach a shadow root safely. host.removeChild(fakeShadowRoot); // Create the real shadow root once we've cleaned up. var realShadowRoot = host.attachShadow({ mode: 'open' }); // Then we can move stuff over from the fake root to the real one. move(fakeShadowRoot, realShadowRoot); // We must find the slots *after* the shadow root is hydrated so we don't get any unwanted ones. var slots = realShadowRoot.querySelectorAll('slot'); // At each Shadow Root, we only care about its slots, not composed slots, // therefore we need to move the children of top level slots, but not others // Also can't 'move' in loop as that will mutate the DOM and ruin the // 'contains' checks for subsequent slots. var topLevelSlots = (function() { var top = [], ref; for (var i = 0, k = slots.length; i < k; i++) { var slot = slots[i]; // Ref is last known top level slot, if current slot is contained by it, // then that slot is nested and can be ignored if (!(ref && ref.contains(slot))) { top.push(slot); ref = slot; } } return top; })(); topLevelSlots.forEach(function(slot) { move(slot, host); }); } // Replaces a script tag with the corresponding style tag. function restyle() { var script = document.currentScript; var style = document.createElement('style'); style.textContent = document.getElementById( script.getAttribute('data-style-id') ).textContent; script.parentNode.replaceChild(style, script); } const funcs = { rehydrate, restyle }; module.exports = function(func, name) { return ( cache[func] || (cache[func] = minify(funcs[func].toString()).code.replace( `function ${func}`, `function ${name}_${func}` )) ); };