chore: update components with documentation

This commit is contained in:
tbitw2549 2024-08-30 00:04:39 +03:00
parent 67d3cadcb2
commit 74231878ea
2 changed files with 41 additions and 12 deletions

View File

@ -1,5 +1,6 @@
import { defineAsyncComponent, defineComponent, h, hydrateOnIdle, hydrateOnInteraction, hydrateOnMediaQuery, hydrateOnVisible, ref, watch } from 'vue'
import { defineAsyncComponent, defineComponent, getCurrentInstance, h, hydrateOnIdle, hydrateOnInteraction, hydrateOnMediaQuery, hydrateOnVisible, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import type { AsyncComponentLoader, HydrationStrategy } from 'vue'
import { onNuxtReady, useNuxtApp } from '#app'
/* @__NO_SIDE_EFFECTS__ */
export const createLazyIOComponent = (loader: AsyncComponentLoader) => {
@ -9,7 +10,12 @@ export const createLazyIOComponent = (loader: AsyncComponentLoader) => {
if (import.meta.server) {
return () => h(defineAsyncComponent(loader), attrs)
}
return () => h(defineAsyncComponent({ loader, hydrate: hydrateOnVisible(attrs.hydrate as IntersectionObserverInit | undefined) }))
const ready = ref(false)
const nuxt = useNuxtApp()
const instance = getCurrentInstance()!
onNuxtReady(() => ready.value = true)
// This is a hack to prevent hydration mismatches for all hydration strategies
return () => ready.value ? h(defineAsyncComponent({ loader, hydrate: hydrateOnVisible(attrs.hydrate as IntersectionObserverInit | undefined) })) : nuxt.isHydrating && instance.vnode.el ? h('div', attrs) : null
},
})
}
@ -22,7 +28,12 @@ export const createLazyNetworkComponent = (loader: AsyncComponentLoader) => {
if (import.meta.server) {
return () => h(defineAsyncComponent(loader), attrs)
}
return () => h(defineAsyncComponent({ loader, hydrate: hydrateOnIdle(attrs.hydrate as number | undefined) }))
const ready = ref(false)
const nuxt = useNuxtApp()
const instance = getCurrentInstance()!
onNuxtReady(() => ready.value = true)
// This one seems to work fine due to the intended use case
return () => ready.value ? h(defineAsyncComponent({ loader, hydrate: hydrateOnIdle(attrs.hydrate as number | undefined) })) : nuxt.isHydrating && instance.vnode.el ? h('div', attrs) : null
},
})
}
@ -35,8 +46,12 @@ export const createLazyEventComponent = (loader: AsyncComponentLoader) => {
if (import.meta.server) {
return () => h(defineAsyncComponent(loader), attrs)
}
const ready = ref(false)
const nuxt = useNuxtApp()
const instance = getCurrentInstance()!
onNuxtReady(() => ready.value = true)
const events: Array<keyof HTMLElementEventMap> = attrs.hydrate as Array<keyof HTMLElementEventMap> ?? ['mouseover']
return () => h(defineAsyncComponent({ loader, hydrate: hydrateOnInteraction(events) }))
return () => ready.value ? h(defineAsyncComponent({ loader, hydrate: hydrateOnInteraction(events) })) : nuxt.isHydrating && instance.vnode.el ? h('div', attrs) : null
},
})
}
@ -49,7 +64,12 @@ export const createLazyMediaComponent = (loader: AsyncComponentLoader) => {
if (import.meta.server) {
return () => h(defineAsyncComponent(loader), attrs)
}
return () => h(defineAsyncComponent({ loader, hydrate: hydrateOnMediaQuery(attrs.hydrate ?? '(min-width: 1px)') }))
const ready = ref(false)
const nuxt = useNuxtApp()
const instance = getCurrentInstance()!
onNuxtReady(() => ready.value = true)
// This one, unlike others, can cause a hydration mismatch even a whole minute after the page loads. Given a query of min-width: 1200px, with a small window, the moment the window expands to at least 1200 it hydrates and causes a hydration mismatch.
return () => ready.value ? h(defineAsyncComponent({ loader, hydrate: hydrateOnMediaQuery(attrs.hydrate ?? '(min-width: 1px)') })) : nuxt.isHydrating && instance.vnode.el ? h('div', attrs) : null
},
})
}
@ -62,12 +82,21 @@ export const createLazyIfComponent = (loader: AsyncComponentLoader) => {
if (import.meta.server) {
return () => h(defineAsyncComponent(loader), attrs)
}
const ready = ref(false)
const nuxt = useNuxtApp()
const instance = getCurrentInstance()!
onNuxtReady(() => ready.value = true)
const shouldHydrate = ref(!!(attrs.hydrate ?? true))
const strategy: HydrationStrategy = (hydrate) => {
if (!shouldHydrate.value) {
const unwatch = watch(shouldHydrate, () => hydrate(), { once: true })
return () => unwatch()
}
return () => h(defineAsyncComponent({ loader, hydrate: strategy }))
hydrate()
return () => {}
}
// This one seems to work fine whenever the hydration condition is achieved at client side. For example, a hydration condition of a ref greater than 2 with a button to increment causes no hydration mismatch after 3 presses of the button.
return () => ready.value ? h(defineAsyncComponent({ loader, hydrate: strategy })) : nuxt.isHydrating && instance.vnode.el ? h('div', attrs) : null
},
})
}

View File

@ -2698,8 +2698,8 @@ describe('lazy import components', () => {
expect(await page.locator('body').getByText('This shouldn\'t be visible at first with network!').all()).toHaveLength(1)
expect(await page.locator('body').getByText('This should be visible at first with viewport!').all()).toHaveLength(1)
expect(await page.locator('body').getByText('This should be visible at first with events!').all()).toHaveLength(2)
// The default value is immediately truthy
//expect(await page.locator('body').getByText('This should be visible at first with conditions!').all()).toHaveLength(2)
// The default value is immediately truthy, however, there is a hydration mismatch without the hack
expect(await page.locator('body').getByText('This should be visible at first with conditions!').all()).toHaveLength(2)
const component = page.locator('#lazyevent')
const rect = (await component.boundingBox())!
await page.mouse.move(rect.x + rect.width / 2, rect.y + rect.height / 2)
@ -2707,11 +2707,11 @@ describe('lazy import components', () => {
expect(await page.locator('body').getByText('This shouldn\'t be visible at first with events!').all()).toHaveLength(1)
await page.locator('#conditionbutton').click()
await page.waitForLoadState('networkidle')
//expect(await page.locator('body').getByText('This shouldn\'t be visible at first with conditions!').all()).toHaveLength(2)
expect(await page.locator('body').getByText('This shouldn\'t be visible at first with conditions!').all()).toHaveLength(2)
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight))
await page.waitForLoadState('networkidle')
expect(await page.locator('body').getByText('This shouldn\'t be visible at first with viewport!').all()).toHaveLength(1)
//expect(await page.locator('body').getByText('This should never be visible!').all()).toHaveLength(1)
expect(await page.locator('body').getByText('This should always be visible!').all()).toHaveLength(1)
await page.close()
})