Simplify nested hydration flow (#7370)

This commit is contained in:
Bjorn Lu 2023-06-27 21:16:10 +08:00 committed by GitHub
parent da56a005d9
commit 83016795e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 51 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Simplify nested hydration flow

View file

@ -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 = [

View file

@ -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;
}

View file

@ -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 {};

View file

@ -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 // 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. // when the parent island hydrates and re-creates this island.
!this.isConnected || if (!this.isConnected) return;
// Wait for parent island to hydrate first so we hydrate top-down.
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();