Skip to content

Commit

Permalink
Fix hydration on slow connection (#8680)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy authored Sep 29, 2023
1 parent c3572fd commit 31c59ad
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-bags-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fix hydration on slow connection
31 changes: 24 additions & 7 deletions packages/astro/src/runtime/server/astro-island.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,34 @@ declare const Astro: {
document.addEventListener('astro:after-swap', this.unmount, { once: true });
}
connectedCallback() {
if (!this.hasAttribute('await-children') || this.firstChild) {
if (
!this.hasAttribute('await-children') ||
document.readyState === 'interactive' ||
document.readyState === 'complete'
) {
this.childrenConnectedCallback();
} else {
// connectedCallback may run *before* children are rendered (ex. HTML streaming)
// If SSR children are expected, but not yet rendered,
// Wait with a mutation observer
new MutationObserver((_, mo) => {
// If SSR children are expected, but not yet rendered, wait with a mutation observer
// for a special marker inserted when rendering islands that signals the end of the island
const onConnected = () => {
document.removeEventListener('DOMContentLoaded', onConnected);
mo.disconnect();
// Wait until the next macrotask to ensure children are really rendered
setTimeout(() => this.childrenConnectedCallback(), 0);
}).observe(this, { childList: true });
this.childrenConnectedCallback();
};
const mo = new MutationObserver(() => {
if (
this.lastChild?.nodeType === Node.COMMENT_NODE &&
this.lastChild.nodeValue === 'astro:end'
) {
this.lastChild.remove();
onConnected();
}
});
mo.observe(this, { childList: true });
// in case the marker comment got stripped and the mutation observer waited indefinitely,
// also wait for DOMContentLoaded as a last resort
document.addEventListener('DOMContentLoaded', onConnected);
}
}
async childrenConnectedCallback() {
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/runtime/server/render/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr

if (island.children) {
island.props['await-children'] = '';
// Marker to signal that Astro island children is completed while streaming
island.children += `<!--astro:end-->`;
}

return {
Expand Down

0 comments on commit 31c59ad

Please sign in to comment.