vue3-lazy-hydration
Version:
Lazy Hydration for Vue 3 SSR
46 lines (45 loc) • 1.59 kB
JavaScript
import { getCurrentInstance, onBeforeMount, onUnmounted, nextTick } from "vue";
import createHydrationCleanup from "../utils/create-hydration-cleanup.mjs";
import createHydrationPromise from "../utils/create-hydration-promise.mjs";
import trackDepsOnRender from "../utils/track-deps-on-render.mjs";
import waitForAsyncComponents from "../utils/wait-for-async-components.mjs";
import ensureParentHasSubTreeEl from "../utils/ensure-parent-has-subtree-el.mjs";
function useLazyHydration() {
const instance = getCurrentInstance();
if (!instance || instance.isMounted) {
throw new Error("useLazyHydration must be called from the setup method.");
}
const willPerformHydration = instance.vnode.el !== null;
instance.vnode.type.__isLazilyHydrated = true;
if (!willPerformHydration) {
return { willPerformHydration, onHydrated: () => {
} };
}
const { cleanup, onCleanup } = createHydrationCleanup();
const {
promise,
resolvePromise: hydrate,
onResolvedPromise: onBeforeHydrate
} = createHydrationPromise(cleanup);
const onHydrated = (cb) => onBeforeHydrate(() => nextTick(() => waitForAsyncComponents(instance, cb)));
instance.type.__asyncLoader = () => promise;
ensureParentHasSubTreeEl(
instance.parent
);
onBeforeMount(() => {
instance.asyncDep = new Promise((r) => {
r(true);
});
});
onBeforeHydrate(() => {
trackDepsOnRender(
instance
);
instance.asyncDep = null;
});
onUnmounted(cleanup);
return { willPerformHydration, hydrate, onHydrated, onCleanup };
}
export {
useLazyHydration as default
};