Simplify nested hydration flow (#7370)
This commit is contained in:
parent
da56a005d9
commit
83016795e9
5 changed files with 24 additions and 51 deletions
5
.changeset/gorgeous-tables-sparkle.md
Normal file
5
.changeset/gorgeous-tables-sparkle.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Simplify nested hydration flow
|
4
.github/scripts/bundle-size.mjs
vendored
4
.github/scripts/bundle-size.mjs
vendored
|
@ -23,7 +23,9 @@ export default async function checkBundleSize({ github, context }) {
|
||||||
...context.repo,
|
...context.repo,
|
||||||
pull_number: PR_NUM,
|
pull_number: PR_NUM,
|
||||||
});
|
});
|
||||||
const clientRuntimeFiles = files.filter(({ filename }) => filename.startsWith(CLIENT_RUNTIME_PATH));
|
const clientRuntimeFiles = files.filter((file) => {
|
||||||
|
return file.filename.startsWith(CLIENT_RUNTIME_PATH) && file.status !== 'removed'
|
||||||
|
});
|
||||||
if (clientRuntimeFiles.length === 0) return;
|
if (clientRuntimeFiles.length === 0) return;
|
||||||
|
|
||||||
const table = [
|
const table = [
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
const HYDRATE_KEY = `astro:hydrate`;
|
|
||||||
function debounce<T extends (...args: any[]) => any>(cb: T, wait = 20) {
|
|
||||||
let h = 0;
|
|
||||||
let callable = (...args: any) => {
|
|
||||||
clearTimeout(h);
|
|
||||||
h = setTimeout(() => cb(...args), wait) as unknown as number;
|
|
||||||
};
|
|
||||||
return callable as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const notify = debounce(() => {
|
|
||||||
window.dispatchEvent(new CustomEvent(HYDRATE_KEY));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!(window as any)[HYDRATE_KEY]) {
|
|
||||||
if ('MutationObserver' in window) {
|
|
||||||
new MutationObserver(notify).observe(document.body, { subtree: true, childList: true });
|
|
||||||
}
|
|
||||||
(window as any)[HYDRATE_KEY] = true;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
import type { GetHydrateCallback, HydrateOptions } from '../../@types/astro';
|
|
||||||
|
|
||||||
type DirectiveLoader = (get: GetHydrateCallback, opts: HydrateOptions, root: HTMLElement) => void;
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
Astro: {
|
|
||||||
idle: DirectiveLoader;
|
|
||||||
load: DirectiveLoader;
|
|
||||||
media: DirectiveLoader;
|
|
||||||
only: DirectiveLoader;
|
|
||||||
visible: DirectiveLoader;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
|
@ -59,7 +59,6 @@ declare const Astro: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async childrenConnectedCallback() {
|
async childrenConnectedCallback() {
|
||||||
window.addEventListener('astro:hydrate', this.hydrate);
|
|
||||||
let beforeHydrationUrl = this.getAttribute('before-hydration-url');
|
let beforeHydrationUrl = this.getAttribute('before-hydration-url');
|
||||||
if (beforeHydrationUrl) {
|
if (beforeHydrationUrl) {
|
||||||
await import(beforeHydrationUrl);
|
await import(beforeHydrationUrl);
|
||||||
|
@ -96,17 +95,22 @@ declare const Astro: {
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
hydrate = () => {
|
hydrate = async () => {
|
||||||
if (
|
// The client directive needs to load the hydrator code before it can hydrate
|
||||||
!this.hydrator ||
|
if (!this.hydrator) return;
|
||||||
// Make sure the island is mounted on the DOM before hydrating. It could be unmounted
|
|
||||||
// when the parent island hydrates and re-creates this island.
|
// Make sure the island is mounted on the DOM before hydrating. It could be unmounted
|
||||||
!this.isConnected ||
|
// when the parent island hydrates and re-creates this island.
|
||||||
// Wait for parent island to hydrate first so we hydrate top-down.
|
if (!this.isConnected) return;
|
||||||
this.parentElement?.closest('astro-island[ssr]')
|
|
||||||
) {
|
// Wait for parent island to hydrate first so we hydrate top-down. The `ssr` attribute
|
||||||
|
// represents that it has not completed hydration yet.
|
||||||
|
const parentSsrIsland = this.parentElement?.closest('astro-island[ssr]');
|
||||||
|
if (parentSsrIsland) {
|
||||||
|
parentSsrIsland.addEventListener('astro:hydrate', this.hydrate, { once: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const slotted = this.querySelectorAll('astro-slot');
|
const slotted = this.querySelectorAll('astro-slot');
|
||||||
const slots: Record<string, string> = {};
|
const slots: Record<string, string> = {};
|
||||||
// Always check to see if there are templates.
|
// Always check to see if there are templates.
|
||||||
|
@ -126,12 +130,11 @@ declare const Astro: {
|
||||||
const props = this.hasAttribute('props')
|
const props = this.hasAttribute('props')
|
||||||
? JSON.parse(this.getAttribute('props')!, reviver)
|
? JSON.parse(this.getAttribute('props')!, reviver)
|
||||||
: {};
|
: {};
|
||||||
this.hydrator(this)(this.Component, props, slots, {
|
await this.hydrator(this)(this.Component, props, slots, {
|
||||||
client: this.getAttribute('client'),
|
client: this.getAttribute('client'),
|
||||||
});
|
});
|
||||||
this.removeAttribute('ssr');
|
this.removeAttribute('ssr');
|
||||||
window.removeEventListener('astro:hydrate', this.hydrate);
|
this.dispatchEvent(new CustomEvent('astro:hydrate'));
|
||||||
window.dispatchEvent(new CustomEvent('astro:hydrate'));
|
|
||||||
};
|
};
|
||||||
attributeChangedCallback() {
|
attributeChangedCallback() {
|
||||||
this.hydrate();
|
this.hydrate();
|
||||||
|
|
Loading…
Reference in a new issue