mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 21:55:11 +00:00
fix: ssr improvement + static vnode rendering
This commit is contained in:
parent
cfb6660fcd
commit
e4c9940269
@ -1,39 +1,62 @@
|
||||
import { createStaticVNode, defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { createStaticVNode, defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, ref, createVNode } from 'vue'
|
||||
import type { Component, Ref, VNode } from 'vue'
|
||||
// import ClientOnly from '#app/components/client-only'
|
||||
import { useObserver } from '#app/utils'
|
||||
import { getFragmentHTML } from '#app/components/utils'
|
||||
import { useNuxtApp } from '#app/nuxt'
|
||||
|
||||
// todo find a better way to do it ?
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export const createLazyIOClientPage = (componentLoader: Component) => {
|
||||
return defineComponent({
|
||||
inheritAttrs: false,
|
||||
setup (_, { attrs }) {
|
||||
setup(_, { attrs }) {
|
||||
|
||||
if (import.meta.server) {
|
||||
return h('div', {}, [
|
||||
h(componentLoader, attrs)
|
||||
])
|
||||
}
|
||||
|
||||
const nuxt = useNuxtApp()
|
||||
const instance = getCurrentInstance()!
|
||||
let vnode: VNode | null = null
|
||||
if (import.meta.client && nuxt.isHydrating && instance.vnode?.el) {
|
||||
vnode = createStaticVNode(getFragmentHTML(instance.vnode.el ?? null, true)?.join('') || '', 1)
|
||||
}
|
||||
const isIntersecting = ref(false)
|
||||
const el: Ref<Element | null> = ref(null)
|
||||
let unobserve: (() => void) | null = null
|
||||
onMounted(() => {
|
||||
const observer = useObserver()
|
||||
unobserve = observer!.observe(el.value as Element, () => {
|
||||
isIntersecting.value = true
|
||||
unobserve?.()
|
||||
unobserve = null
|
||||
|
||||
// todo can be refactored
|
||||
if (instance.vnode.el && nuxt.isHydrating) {
|
||||
isIntersecting.value = elementIsVisibleInViewport(instance.vnode.el as Element)
|
||||
}
|
||||
|
||||
if (!isIntersecting.value) {
|
||||
onMounted(() => {
|
||||
const observer = useObserver()
|
||||
unobserve = observer!.observe(el.value as Element, () => {
|
||||
isIntersecting.value = true
|
||||
unobserve?.()
|
||||
unobserve = null
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
unobserve?.()
|
||||
unobserve = null
|
||||
})
|
||||
return () => h('div', { ref: el }, [
|
||||
isIntersecting.value ? h(componentLoader, attrs) : vnode,
|
||||
])
|
||||
return () => {
|
||||
return h('div', { ref: el }, [
|
||||
isIntersecting.value ? h(componentLoader, attrs) : (instance.vnode.el && nuxt.isHydrating) ? createVNode(createStaticVNode(getFragmentHTML(instance.vnode.el ?? null, true)?.join('') || '', 1)) : null,
|
||||
])
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -42,7 +65,7 @@ export const createLazyIOClientPage = (componentLoader: Component) => {
|
||||
export const createLazyNetworkClientPage = (componentLoader: Component) => {
|
||||
return defineComponent({
|
||||
inheritAttrs: false,
|
||||
setup (_, { attrs }) {
|
||||
setup(_, { attrs }) {
|
||||
const nuxt = useNuxtApp()
|
||||
const instance = getCurrentInstance()!
|
||||
let vnode: VNode | null = null
|
||||
|
Loading…
Reference in New Issue
Block a user