feat: lazy hydration strategies for async components by yyx990803 · Pull Request #11458 · vuejs/core (original) (raw)

Note: API has been adjusted in #11530

Async components can now control when they are hydrated by providing a hydration strategy.

Hydrate on Idle

Hydrates via requestIdleCallback:

import { defineAsyncComponent, hydrateOnIdle } from 'vue'

const AsyncComp = defineAsyncComponent({ loader: () => import('./Comp.vue'), hydrate: hydrateOnIdle(/* optionally pass a max timeout */) })

Hydrate on Visible

Hydrate when element(s) become visible via IntersectionObserver.

import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const AsyncComp = defineAsyncComponent({ loader: () => import('./Comp.vue'), hydrate: hydrateOnVisible() })

Can optionally pass in an options object value for the observer:

hydrateOnVisible({ rootMargin: '100px' })

Hydrate on Media Query

Hydrates when the specified media query matches.

import { defineAsyncComponent, hydrateOnMediaQuery } from 'vue'

const AsyncComp = defineAsyncComponent({ loader: () => import('./Comp.vue'), hydrate: hydrateOnMediaQuery('(max-width:500px)') })

Hydrate on Interaction

Hydrates when specified event(s) are triggered on the component element(s). The event that triggered the hydration will also be replayed once hydration is complete.

import { defineAsyncComponent, hydrateOnInteraction } from 'vue'

const AsyncComp = defineAsyncComponent({ loader: () => import('./Comp.vue'), hydrate: hydrateOnInteraction('click') })

Can also be a list of multiple event types:

hydrateOnInteraction(['wheel', 'mouseover'])

Custom Strategy

import { defineAsyncComponent, type HydrationStrategy } from 'vue'

const myStrategy: HydrationStrategy = (hydrate, forEachElement) => { // forEachElement is a helper to iterate through all the root elememts // in the component's non-hydrated DOM, since the root can be a fragment // instead of a single element forEachElement(el => { // ... }) // call hydrate when ready hydrate() return () => { // return a teardown function if needed } }

const AsyncComp = defineAsyncComponent({ loader: () => import('./Comp.vue'), hydrate: myStrategy })