Fix hydration on slow connection (#8680)
This commit is contained in:
parent
c3572fd5e0
commit
31c59ad8b6
3 changed files with 31 additions and 7 deletions
5
.changeset/curly-bags-attack.md
Normal file
5
.changeset/curly-bags-attack.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix hydration on slow connection
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue