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 });
|
document.addEventListener('astro:after-swap', this.unmount, { once: true });
|
||||||
}
|
}
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
if (!this.hasAttribute('await-children') || this.firstChild) {
|
if (
|
||||||
|
!this.hasAttribute('await-children') ||
|
||||||
|
document.readyState === 'interactive' ||
|
||||||
|
document.readyState === 'complete'
|
||||||
|
) {
|
||||||
this.childrenConnectedCallback();
|
this.childrenConnectedCallback();
|
||||||
} else {
|
} else {
|
||||||
// connectedCallback may run *before* children are rendered (ex. HTML streaming)
|
// connectedCallback may run *before* children are rendered (ex. HTML streaming)
|
||||||
// If SSR children are expected, but not yet rendered,
|
// If SSR children are expected, but not yet rendered, wait with a mutation observer
|
||||||
// Wait with a mutation observer
|
// for a special marker inserted when rendering islands that signals the end of the island
|
||||||
new MutationObserver((_, mo) => {
|
const onConnected = () => {
|
||||||
|
document.removeEventListener('DOMContentLoaded', onConnected);
|
||||||
mo.disconnect();
|
mo.disconnect();
|
||||||
// Wait until the next macrotask to ensure children are really rendered
|
this.childrenConnectedCallback();
|
||||||
setTimeout(() => this.childrenConnectedCallback(), 0);
|
};
|
||||||
}).observe(this, { childList: true });
|
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() {
|
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) {
|
if (island.children) {
|
||||||
island.props['await-children'] = '';
|
island.props['await-children'] = '';
|
||||||
|
// Marker to signal that Astro island children is completed while streaming
|
||||||
|
island.children += `<!--astro:end-->`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue