In this case you could use MutationObserver - although we are doing manually the logic web components provide, but my point is that you can do it also without using web components. My code doesn't include attribute changes, but this should be possible to also do with MutationObserver.
<body>
<script>
const onRemoteFragmentMount = async (el) => {
const src = el.getAttribute("src");
const result = await fetch(src).then((res) => res.text());
el.innerHTML = result;
};
const callback = (mutationsList, observer) => {
for (let mutation of mutationsList) {
if (mutation.type === "childList") {
mutation.addedNodes.forEach((node) => {
if (node.tagName === "REMOTE-FRAGMENT") {
onRemoteFragmentMount(node);
}
});
}
}
};
const observer = new MutationObserver(callback);
const bodyElement = document.querySelector("body");
observer.observe(bodyElement, {
childList: true,
subtree: true,
});
</script>
<remote-fragment src="..." />
</body>