UNPKG

vue3-lazy-hydration

Version:
97 lines (96 loc) 3.15 kB
import { markRaw, defineComponent, getCurrentInstance, ref, createVNode, handleError } from "vue"; import { isObject, isFunction } from "./helpers.mjs"; import useLazyHydration from "../composables/useLazyHydration.mjs"; function createInnerComp(comp, { vnode: { ref: refOwner, props, children } }) { const vnode = createVNode(comp, props, children); vnode.ref = refOwner; return vnode; } function createHydrationWrapper(source, onSetup) { let pendingRequest = null; let resolvedComp; const loader = isFunction(source) ? source : () => Promise.resolve(source); const load = () => { let thisRequest; if (pendingRequest !== null) { return pendingRequest; } return thisRequest = pendingRequest = loader().catch((err) => { throw err instanceof Error ? err : new Error(String(err)); }).then((comp) => { if (thisRequest !== pendingRequest && pendingRequest !== null) { return pendingRequest; } if (process.env.NODE_ENV === "development" && !comp) { console.warn( `Async lazily hydrated wrapped component loader resolved to undefined.` ); } if (comp && (comp.__esModule || comp[Symbol.toStringTag] === "Module")) { comp = comp.default; } if (process.env.NODE_ENV === "development" && comp && !isObject(comp) && !isFunction(comp)) { throw new Error( `Invalid async lazily hydrated wrapped component load result: ${comp}` ); } resolvedComp = comp; return comp; }); }; return markRaw( defineComponent({ name: "LazyHydrationWrapper", inheritAttrs: false, suspensible: false, emits: ["hydrated"], get __asyncResolved() { return resolvedComp; }, setup(_, { emit }) { const instance = getCurrentInstance(); const onError = (err) => { pendingRequest = null; handleError(err, instance, 13); }; const loaded = ref(false); const result = useLazyHydration(); if (typeof window === "undefined") { return load().then((comp) => () => createInnerComp(comp, instance)).catch((err) => { onError(err); return () => null; }); } if (!result.willPerformHydration) { if (resolvedComp) { return () => createInnerComp(resolvedComp, instance); } load().then(() => { loaded.value = true; }).catch((err) => { onError(err); }); return () => { if (loaded.value && resolvedComp) { return createInnerComp(resolvedComp, instance); } return null; }; } const { hydrate } = result; result.hydrate = () => load().then(() => { loaded.value = true; void hydrate(); }).catch((err) => { onError(err); }); result.onHydrated(() => emit("hydrated")); onSetup(result); return () => createInnerComp(resolvedComp, instance); } }) ); } export { createHydrationWrapper as default };