summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Bjorn Lu <bjornlu.dev@gmail.com> 2023-06-27 21:16:10 +0800
committerGravatar GitHub <noreply@github.com> 2023-06-27 21:16:10 +0800
commit83016795e9e149bc64e2441d477cf8c65ef5a117 (patch)
tree77159686ed371c94eb91b4b32cd4b6a244c7d698
parentda56a005d92517e6e86b3a1c378a534e001a3aa4 (diff)
downloadastro-83016795e9e149bc64e2441d477cf8c65ef5a117.tar.gz
astro-83016795e9e149bc64e2441d477cf8c65ef5a117.tar.zst
astro-83016795e9e149bc64e2441d477cf8c65ef5a117.zip
Simplify nested hydration flow (#7370)
-rw-r--r--.changeset/gorgeous-tables-sparkle.md5
-rw-r--r--.github/scripts/bundle-size.mjs4
-rw-r--r--packages/astro/src/runtime/client/events.ts20
-rw-r--r--packages/astro/src/runtime/client/hydration-directives.d.ts17
-rw-r--r--packages/astro/src/runtime/server/astro-island.ts29
5 files changed, 24 insertions, 51 deletions
diff --git a/.changeset/gorgeous-tables-sparkle.md b/.changeset/gorgeous-tables-sparkle.md
new file mode 100644
index 000000000..0613fac56
--- /dev/null
+++ b/.changeset/gorgeous-tables-sparkle.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Simplify nested hydration flow
diff --git a/.github/scripts/bundle-size.mjs b/.github/scripts/bundle-size.mjs
index 618d6e8cb..49c3c5bed 100644
--- a/.github/scripts/bundle-size.mjs
+++ b/.github/scripts/bundle-size.mjs
@@ -23,7 +23,9 @@ export default async function checkBundleSize({ github, context }) {
...context.repo,
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;
const table = [
diff --git a/packages/astro/src/runtime/client/events.ts b/packages/astro/src/runtime/client/events.ts
deleted file mode 100644
index 93a8c2600..000000000
--- a/packages/astro/src/runtime/client/events.ts
+++ /dev/null
@@ -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;
-}
diff --git a/packages/astro/src/runtime/client/hydration-directives.d.ts b/packages/astro/src/runtime/client/hydration-directives.d.ts
deleted file mode 100644
index 6832ab24f..000000000
--- a/packages/astro/src/runtime/client/hydration-directives.d.ts
+++ /dev/null
@@ -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 {};
diff --git a/packages/astro/src/runtime/server/astro-island.ts b/packages/astro/src/runtime/server/astro-island.ts
index b24e6c0be..3f93cd817 100644
--- a/packages/astro/src/runtime/server/astro-island.ts
+++ b/packages/astro/src/runtime/server/astro-island.ts
@@ -59,7 +59,6 @@ declare const Astro: {
}
}
async childrenConnectedCallback() {
- window.addEventListener('astro:hydrate', this.hydrate);
let beforeHydrationUrl = this.getAttribute('before-hydration-url');
if (beforeHydrationUrl) {
await import(beforeHydrationUrl);
@@ -96,17 +95,22 @@ declare const Astro: {
this
);
}
- hydrate = () => {
- if (
- !this.hydrator ||
- // 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.
- !this.isConnected ||
- // Wait for parent island to hydrate first so we hydrate top-down.
- this.parentElement?.closest('astro-island[ssr]')
- ) {
+ hydrate = async () => {
+ // The client directive needs to load the hydrator code before it can hydrate
+ 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.
+ if (!this.isConnected) return;
+
+ // 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;
}
+
const slotted = this.querySelectorAll('astro-slot');
const slots: Record<string, string> = {};
// Always check to see if there are templates.
@@ -126,12 +130,11 @@ declare const Astro: {
const props = this.hasAttribute('props')
? 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'),
});
this.removeAttribute('ssr');
- window.removeEventListener('astro:hydrate', this.hydrate);
- window.dispatchEvent(new CustomEvent('astro:hydrate'));
+ this.dispatchEvent(new CustomEvent('astro:hydrate'));
};
attributeChangedCallback() {
this.hydrate();