UNPKG

@modern-js/runtime-utils

Version:

A Progressive React Framework for modern web development.

106 lines (105 loc) 4.37 kB
import "node:module"; import { jsx } from "react/jsx-runtime"; import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants"; import { Suspense } from "react"; import { Outlet, Route, createRoutesFromElements } from "react-router"; import { time } from "../time.mjs"; import { getAsyncLocalStorage } from "../universal/async_storage.mjs"; import { DeferredData, activeDeferreds as external_deferreds_mjs_activeDeferreds } from "./deferreds.mjs"; const privateDefer = (data)=>new DeferredData(data); const transformNestedRoutes = (routes)=>{ const routeElements = []; for (const route of routes){ const routeElement = renderNestedRoute(route); routeElements.push(routeElement); } return createRoutesFromElements(routeElements); }; const renderNestedRoute = (nestedRoute, options = {})=>{ const { children, index, id, component, isRoot, lazyImport, config, handle } = nestedRoute; const Component = component; const { parent, props = {} } = options; const routeProps = { caseSensitive: nestedRoute.caseSensitive, path: nestedRoute.path, id: nestedRoute.id, loader: createLoader(nestedRoute), action: nestedRoute.action, hasErrorBoundary: nestedRoute.hasErrorBoundary, shouldRevalidate: nestedRoute.shouldRevalidate, handle: { ...handle, ...'object' == typeof config ? config?.handle : {} }, index: nestedRoute.index, element: nestedRoute.element, errorElement: nestedRoute.errorElement }; if (nestedRoute.error) { const errorElement = /*#__PURE__*/ jsx(nestedRoute.error, {}); routeProps.errorElement = errorElement; } let element; if (Component) if (parent?.loading && lazyImport) { const Loading = parent.loading; element = isLoadableComponent(Component) ? /*#__PURE__*/ jsx(Component, { fallback: /*#__PURE__*/ jsx(Loading, {}) }) : /*#__PURE__*/ jsx(Suspense, { fallback: /*#__PURE__*/ jsx(Loading, {}), children: /*#__PURE__*/ jsx(Component, {}) }); } else element = isLoadableComponent(Component) && lazyImport ? /*#__PURE__*/ jsx(Component, {}) : isRoot ? /*#__PURE__*/ jsx(Component, { ...props }) : lazyImport ? /*#__PURE__*/ jsx(Suspense, { fallback: null, children: /*#__PURE__*/ jsx(Component, {}) }) : /*#__PURE__*/ jsx(Component, {}); else { nestedRoute.loading = parent?.loading; routeProps.element = /*#__PURE__*/ jsx(Outlet, {}); } if (element) routeProps.element = element; const childElements = children?.map((childRoute)=>renderNestedRoute(childRoute, { parent: nestedRoute })); const routeElement = index ? /*#__PURE__*/ jsx(Route, { ...routeProps, index: true }, id) : /*#__PURE__*/ jsx(Route, { ...routeProps, index: false, children: childElements }, id); return routeElement; }; function isPlainObject(value) { return null != value && 'object' == typeof value && Object.getPrototypeOf(value) === Object.prototype; } function createLoader(route) { const { loader } = route; if (loader) return async (args)=>{ if ('function' == typeof route.lazyImport) route.lazyImport(); const end = time(); const res = await loader(args); let activeDeferreds = null; activeDeferreds = "u" < typeof document ? (await getAsyncLocalStorage())?.useContext()?.activeDeferreds : external_deferreds_mjs_activeDeferreds; if (isPlainObject(res)) { const deferredData = privateDefer(res); activeDeferreds.set(route.id, deferredData); } const cost = end(); if ("u" < typeof document) { const storage = await getAsyncLocalStorage(); storage?.useContext().monitors?.timing(`${LOADER_REPORTER_NAME}-${route.id?.replace(/\//g, '_')}`, cost); } return res; }; return ()=>{ if ('function' == typeof route.lazyImport) route.lazyImport(); return null; }; } function isLoadableComponent(component) { return component && 'Loadable' === component.displayName && component.preload && 'function' == typeof component.preload; } export { renderNestedRoute, transformNestedRoutes };