From 9be2c891422b6309c4abcbde72e4650ef88ee28d Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sat, 17 Aug 2024 10:22:04 +0300 Subject: [PATCH 01/10] perf(hydration): avoid observer if element is in viewport --- packages/runtime-core/src/hydrationStrategies.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 51200fc1c34..44db2ac9854 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -26,6 +26,14 @@ export const hydrateOnIdle: HydrationStrategyFactory = return () => cancelIdleCallback(id) } +function elementIsVisibleInViewport (el: Element) { + const { top, left, bottom, right } = el.getBoundingClientRect() + const { innerHeight, innerWidth } = window + return ((top > 0 && top < innerHeight) || + (bottom > 0 && bottom < innerHeight)) && + ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) +} + export const hydrateOnVisible: HydrationStrategyFactory< IntersectionObserverInit > = opts => (hydrate, forEach) => { @@ -37,7 +45,13 @@ export const hydrateOnVisible: HydrationStrategyFactory< break } }, opts) - forEach(el => ob.observe(el)) + forEach(el => { + if (elementIsVisibleInViewport(el)){ + hydrate() + return () => ob.disconnect() + } + ob.observe(el) + }) return () => ob.disconnect() } From ea8b5ee07996e8c4734c043ff7bb7effc9e2df74 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sat, 17 Aug 2024 12:14:26 +0300 Subject: [PATCH 02/10] fix: disable eslint warning --- packages/runtime-core/src/hydrationStrategies.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 44db2ac9854..bd202e72f2a 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -28,6 +28,7 @@ export const hydrateOnIdle: HydrationStrategyFactory = function elementIsVisibleInViewport (el: Element) { const { top, left, bottom, right } = el.getBoundingClientRect() + // eslint-disable-next-line no-restricted-globals const { innerHeight, innerWidth } = window return ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && From 72d8ec777454ca7676d63dbf9043cf9f12e6bde1 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 17 Aug 2024 09:15:17 +0000 Subject: [PATCH 03/10] [autofix.ci] apply automated fixes --- packages/runtime-core/src/hydrationStrategies.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index bd202e72f2a..8248ed6b79e 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -26,13 +26,14 @@ export const hydrateOnIdle: HydrationStrategyFactory = return () => cancelIdleCallback(id) } -function elementIsVisibleInViewport (el: Element) { +function elementIsVisibleInViewport(el: Element) { const { top, left, bottom, right } = el.getBoundingClientRect() // eslint-disable-next-line no-restricted-globals const { innerHeight, innerWidth } = window - return ((top > 0 && top < innerHeight) || - (bottom > 0 && bottom < innerHeight)) && + return ( + ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) + ) } export const hydrateOnVisible: HydrationStrategyFactory< @@ -47,7 +48,7 @@ export const hydrateOnVisible: HydrationStrategyFactory< } }, opts) forEach(el => { - if (elementIsVisibleInViewport(el)){ + if (elementIsVisibleInViewport(el)) { hydrate() return () => ob.disconnect() } From d07ed1d2aa2d582d1feff4dc8e65f113c9bd65cf Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sat, 17 Aug 2024 12:18:49 +0300 Subject: [PATCH 04/10] perf: disconnect observer eagerly --- packages/runtime-core/src/hydrationStrategies.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 8248ed6b79e..8b88bb36cd4 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -50,7 +50,8 @@ export const hydrateOnVisible: HydrationStrategyFactory< forEach(el => { if (elementIsVisibleInViewport(el)) { hydrate() - return () => ob.disconnect() + ob.disconnect() + return () => {} } ob.observe(el) }) From 9c76928269189110fe8f388bd486e9b2d77a62b3 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sun, 15 Sep 2024 08:50:11 +0300 Subject: [PATCH 05/10] fix: break loop if return value is false --- packages/runtime-core/src/hydrationStrategies.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 8b88bb36cd4..ac84286b8a1 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -109,7 +109,10 @@ export function forEachElement(node: Node, cb: (el: Element) => void): void { let next = node.nextSibling while (next) { if (next.nodeType === DOMNodeTypes.ELEMENT) { - cb(next as Element) + const result = cb(next as Element) + if (result === false) { + break + } } else if (isComment(next)) { if (next.data === ']') { if (--depth === 0) break From 7509c9dfae3bf5fa3f7b920caa2cb231778ef6cd Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sun, 15 Sep 2024 08:51:01 +0300 Subject: [PATCH 06/10] fix: return false --- packages/runtime-core/src/hydrationStrategies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index ac84286b8a1..5c3a29271ae 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -51,7 +51,7 @@ export const hydrateOnVisible: HydrationStrategyFactory< if (elementIsVisibleInViewport(el)) { hydrate() ob.disconnect() - return () => {} + return false } ob.observe(el) }) From 6de9b50fce5cb9f5e02ff260c88f2c1fcf9dc6b2 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sun, 15 Sep 2024 08:52:40 +0300 Subject: [PATCH 07/10] types: add false to return types --- packages/runtime-core/src/hydrationStrategies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 5c3a29271ae..962af040bb3 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -12,7 +12,7 @@ import { DOMNodeTypes, isComment } from './hydration' */ export type HydrationStrategy = ( hydrate: () => void, - forEachElement: (cb: (el: Element) => any) => void, + forEachElement: (cb: (el: Element) => any) => void | false, ) => (() => void) | void export type HydrationStrategyFactory = ( From 3bb9ff7bbf0dba52b45242a906c032519dbb4170 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sun, 15 Sep 2024 08:55:50 +0300 Subject: [PATCH 08/10] types: fix type in forEachElement --- packages/runtime-core/src/hydrationStrategies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 962af040bb3..bd6dfa4ae9a 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -102,7 +102,7 @@ export const hydrateOnInteraction: HydrationStrategyFactory< return teardown } -export function forEachElement(node: Node, cb: (el: Element) => void): void { +export function forEachElement(node: Node, cb: (el: Element) => void | false): void { // fragment if (isComment(node) && node.data === '[') { let depth = 1 From 828c5d2b5ed6dc3f2a5dd13b7286001ac4fc5033 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Sun, 15 Sep 2024 08:56:08 +0300 Subject: [PATCH 09/10] chore: revert unnecessary type annotation --- packages/runtime-core/src/hydrationStrategies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index bd6dfa4ae9a..4ca75990bfb 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -12,7 +12,7 @@ import { DOMNodeTypes, isComment } from './hydration' */ export type HydrationStrategy = ( hydrate: () => void, - forEachElement: (cb: (el: Element) => any) => void | false, + forEachElement: (cb: (el: Element) => any) => void, ) => (() => void) | void export type HydrationStrategyFactory = ( From 72c9bfc3ea7775ccd8096fc693ab7eee4852da36 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 15 Sep 2024 05:56:58 +0000 Subject: [PATCH 10/10] [autofix.ci] apply automated fixes --- packages/runtime-core/src/hydrationStrategies.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/hydrationStrategies.ts b/packages/runtime-core/src/hydrationStrategies.ts index 4ca75990bfb..791ca9e5254 100644 --- a/packages/runtime-core/src/hydrationStrategies.ts +++ b/packages/runtime-core/src/hydrationStrategies.ts @@ -102,7 +102,10 @@ export const hydrateOnInteraction: HydrationStrategyFactory< return teardown } -export function forEachElement(node: Node, cb: (el: Element) => void | false): void { +export function forEachElement( + node: Node, + cb: (el: Element) => void | false, +): void { // fragment if (isComment(node) && node.data === '[') { let depth = 1