Skip to content

Instantly share code, notes, and snippets.

@julianburr
Last active September 22, 2024 08:57
Show Gist options
  • Save julianburr/c76b4415656204b152d1cd0afe91708d to your computer and use it in GitHub Desktop.
Save julianburr/c76b4415656204b152d1cd0afe91708d to your computer and use it in GitHub Desktop.
Minified bit of Javascript needed to allow out-of-order streaming
window.customElements.define('suspense-content', class SuspenseContent extends HTMLElement {
connectedCallback () {
// Assume previous sibling is the `<template>` element
const content = this.previousElementSibling.content;
// Get `target-id` from custom element attributes and find fallback placeholder based on it
const id = this.getAttribute('target-id');
const target = document.querySelector('[data-suspense-id="' + id + '"]');
// Replace fallback content with actual content
target.innerHTML = '';
while (content.firstChild) {
target.appendChild(content.firstChild);
}
}
});
@julianburr
Copy link
Author

julianburr commented Sep 22, 2024

Example usage when streaming on the server:

// Inject the JS once per response
res.write(`<script>window.customElements.define("suspense-content",class e extends HTMLElement{connectedCallback(){let e=this.previousElementSibling.content,t=this.getAttribute("target-id"),n=document.querySelector('[data-suspense-id="'+t+'"]');for(n.innerHTML="";e.firstChild;)n.appendChild(e.firstChild)}});</script>`);

// Write the fallback to the stream immediately
res.write(`<div data-suspense-id="1">Fallback...</div>`);

// When original content is ready, use `template` and `suspense-content` to replace the fallback
await something();
res.write(`
  <template>Actual content...</template>
  <suspense-content target-id="1"></suspense-content>
`);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment