everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 22.2 kB
Source Map (JSON)
{"version":3,"file":"hydrate.cjs","names":["getRuntimeConfig","getCspNonce","defaultQueryClient","createApiClient","createAuthClient"],"sources":["../../src/ui/hydrate.tsx"],"sourcesContent":["/**\n * Client bootstrap — creates browser-side QueryClient, Router, and auth/API\n * clients; composes the route tree from the runtime-config payload before\n * hydration (payload -> registerRemotes -> loadRemote route configs ->\n * constructTree -> hydrateRoot(RouterClient)). Called from the host-rendered\n * HTML shell via the app's thin entry/hydrate stubs. The build's MF runtime\n * owns the page's share scope — the global registerRemotes/loadRemote API\n * bridges it (one React/router across the core client and plugin containers\n * by share-scope negotiation).\n */\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { ClientRuntimeConfig } from \"../types\";\nimport { type ClientServiceConfig, createApiClient } from \"./api\";\nimport { createAuthClient } from \"./auth\";\nimport {\n CORE_UI_PLUGIN_KEY,\n ComposePayloadSchema,\n constructTree,\n type NavManifest,\n type PluginManifest,\n parsePluginManifest,\n type RouteConfigModule,\n} from \"./manifest\";\nimport { defaultQueryClient } from \"./router-defaults\";\nimport { getCspNonce, getRuntimeConfig } from \"./runtime\";\nimport type { AppRouterFactory } from \"./types\";\n\ndeclare global {\n interface Window {\n __EVERYTHING_DEV_HYDRATE_PROMISE__?: Promise<void>;\n __EVERYTHING_DEV_SSR__?: boolean;\n __CLIENT_PROGRESS__?: string[];\n $_TSR?: unknown;\n }\n}\n\nconst mark = (message: string) => {\n const progress = window.__CLIENT_PROGRESS__ ?? [];\n window.__CLIENT_PROGRESS__ = [...progress, message];\n if (import.meta.env.DEV) console.log(`[Hydrate] ${message}`);\n};\n\nfunction isAbsoluteHttpUrl(value: string | undefined): value is string {\n if (!value) return false;\n try {\n const url = new URL(value);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nexport type { AppRouterFactory } from \"./types\";\n\nexport interface CoreHydrateOptions {\n /**\n * Loads the app's generated core route config — the only app-specific\n * input; clients, compose machinery, and the router come from the package.\n */\n routeConfig: () => Promise<RouteConfigModule | { default: RouteConfigModule }>;\n /**\n * Loads the app's generated core manifest — the degradation target when the\n * runtime config carries no (or no usable) compose payload: a plugin-free\n * deployment has no payload at all, yet the core-only tree is still the\n * tree. Absent, a payload-less page cannot construct a tree. The value is\n * parsed through the manifest contract at the boundary (a skewed version\n * or shape fails loudly here).\n */\n manifest?: () => Promise<unknown>;\n /**\n * The app's authored router factory — notFound/pending/error components,\n * scroll behavior, and router defaults live there. Absent, the framework's\n * own factory runs.\n */\n createRouter?: AppRouterFactory;\n /** The app's query client factory (staleTime, gcTime, …). Absent, the framework default. */\n createQueryClient?: () => QueryClient;\n /** Overrides the runtime config source (tests, embeds). */\n config?: ClientRuntimeConfig;\n /** Localized copy for the API connection-failure toast (see `createApiClient`). */\n apiConnectionError?: ClientServiceConfig[\"connectionError\"];\n}\n\ninterface ComposedTree {\n routeTree: unknown;\n nav: NavManifest;\n /** `true` when plugin composition failed and only the core tree is usable. */\n degraded: boolean;\n}\n\n/**\n * Manifest composition: reconstruct the server's tree from the payload — the\n * same manifests, the same MF names, the same construction code. Digest\n * parity proves the SSR'd tree and this tree are identical before hydrate;\n * any failure degrades to the core-only tree (still a real route tree — the\n * page must render, just without plugin routes) rather than leaving the\n * router without a tree.\n */\nasync function composeFromPayload(\n runtimeConfig: ClientRuntimeConfig,\n coreRouteConfig: RouteConfigModule,\n coreManifest: PluginManifest | undefined,\n): Promise<ComposedTree | undefined> {\n const coreUiName = runtimeConfig.ui?.name ?? CORE_UI_PLUGIN_KEY;\n\n // The core-only tree is the degradation target for every failure below —\n // the payload's core manifest plus the app's own route config, no remotes.\n const composeCoreOnly = async (\n candidateManifests: PluginManifest[],\n ): Promise<ComposedTree | undefined> => {\n try {\n const core = candidateManifests.find((m) => m.name === CORE_UI_PLUGIN_KEY);\n if (!core) return undefined;\n const tree = await constructTree({\n name: \"core-fallback\",\n plugins: [{ key: core.name, mfName: coreUiName }],\n resolve: async (ref) => ({\n key: ref.key,\n manifest: core,\n routeConfig: coreRouteConfig,\n }),\n rootOptions: coreRouteConfig.rootMeta,\n });\n mark(\n `core-only tree constructed: ${tree.manifests.length} source(s), ${tree.nav.items.length} nav item(s)`,\n );\n return { routeTree: tree.rootRoute, nav: tree.nav, degraded: true };\n } catch (error) {\n console.error(\"[Hydrate] Core-only fallback failed:\", error);\n mark(`CORE-ONLY FALLBACK ERROR: ${(error as Error).message}`);\n return undefined;\n }\n };\n\n const payload = runtimeConfig.ui?.compose;\n if (!payload?.remotes) {\n // No payload at all — a plugin-free deployment. The core-only tree IS\n // the tree; without the app manifest there is nothing to construct.\n return coreManifest ? composeCoreOnly([coreManifest]) : undefined;\n }\n\n const parsed = ComposePayloadSchema.safeParse(payload);\n if (!parsed.success) {\n mark(`compose payload malformed: ${parsed.error.message}`);\n return coreManifest ? composeCoreOnly([coreManifest]) : undefined;\n }\n const { manifests } = parsed.data;\n const manifestByKey = new Map(manifests.map((m) => [m.name, m]));\n\n try {\n const { registerRemotes, loadRemote } = await import(\"@module-federation/enhanced/runtime\");\n\n mark(`compose payload: digest ${payload.digest}, ${payload.remotes.length} remote(s)`);\n\n registerRemotes(\n payload.remotes.map((remote) => ({\n name: remote.name,\n alias: remote.name,\n // Manifest-driven registration: the manifest carries the remote's\n // true container identity (its build-time package name), which the\n // plain remoteEntry URL cannot resolve — the entry script's global\n // name doesn't match the registered name. Versioned deploys carry\n // the (hashed) manifest URL in the payload; legacy payloads derive\n // it by stripping the fixed entry name. Only absolute URLs qualify —\n // a relative manifestUrl would resolve against the page origin and\n // register the wrong container.\n entry: isAbsoluteHttpUrl(remote.manifestUrl)\n ? remote.manifestUrl\n : remote.entry.replace(/\\/?remoteEntry\\.js$/, \"/mf-manifest.json\"),\n })),\n );\n for (const remote of payload.remotes) {\n mark(`remote registered ${remote.name} @ ${remote.entry}`);\n }\n\n // Per-source isolation (ADR 0024 §5): a remote whose route config fails\n // to load drops only its own routes. The dropped set degrades the compose\n // (client-render — the SSR'd tree included it), never the whole page.\n const loadedRouteConfigs = new Map<string, RouteConfigModule>();\n const dropped: string[] = [];\n const healthyManifests: PluginManifest[] = [];\n for (const manifest of manifests) {\n if (manifest.name === CORE_UI_PLUGIN_KEY) {\n healthyManifests.push(manifest);\n continue;\n }\n const remote = payload.remotes.find((r) => r.key === manifest.name);\n if (!remote) {\n dropped.push(manifest.name);\n mark(`dropped ${manifest.name} — payload has no matching remote`);\n continue;\n }\n try {\n const mod = await loadRemote(`${remote.name}/routeConfig`, { from: \"build\" });\n const routeConfig = ((mod as { default?: RouteConfigModule })?.default ??\n mod) as RouteConfigModule;\n if (!routeConfig?.routeConfigLoaders) {\n throw new Error(`loadRemote(${remote.name}/routeConfig) returned no route config`);\n }\n loadedRouteConfigs.set(manifest.name, routeConfig);\n healthyManifests.push(manifest);\n mark(`loaded ${remote.name}/routeConfig`);\n } catch (error) {\n dropped.push(manifest.name);\n mark(`dropped ${manifest.name} — ${(error as Error).message}`);\n }\n }\n\n const tree = await constructTree({\n name: \"client\",\n plugins: healthyManifests.map((manifest) => {\n const remote = payload.remotes.find((r) => r.key === manifest.name);\n return {\n key: manifest.name,\n mfName:\n remote?.name ?? (manifest.name === CORE_UI_PLUGIN_KEY ? coreUiName : manifest.name),\n };\n }),\n resolve: async (ref) => {\n if (ref.key === CORE_UI_PLUGIN_KEY) {\n const manifest = manifestByKey.get(ref.key);\n if (!manifest) throw new Error(`compose payload has no manifest for \"${ref.key}\"`);\n return { key: ref.key, manifest, routeConfig: coreRouteConfig };\n }\n const manifest = manifestByKey.get(ref.key);\n const routeConfig = loadedRouteConfigs.get(ref.key);\n if (!manifest || !routeConfig) {\n throw new Error(`composition source \"${ref.key}\" is not fully resolved`);\n }\n return { key: ref.key, manifest, routeConfig };\n },\n rootOptions: coreRouteConfig.rootMeta,\n });\n\n if (dropped.length > 0) {\n mark(`degraded compose: ${dropped.join(\", \")} dropped — client-render`);\n return { routeTree: tree.rootRoute, nav: tree.nav, degraded: true };\n }\n\n if (tree.digest !== payload.digest) {\n console.warn(\n `[Hydrate] Compose digest mismatch (client ${tree.digest} vs server ${payload.digest}); core-only fallback`,\n );\n mark(`DIGEST PARITY FAILURE server=${payload.digest} client=${tree.digest}`);\n return composeCoreOnly(manifests);\n }\n\n mark(\n `tree constructed: ${tree.manifests.length} source(s), ${tree.nav.items.length} nav item(s)`,\n );\n return { routeTree: tree.rootRoute, nav: tree.nav, degraded: false };\n } catch (error) {\n console.error(\"[Hydrate] Client compose failed; core-only fallback:\", error);\n mark(`CLIENT COMPOSE ERROR: ${(error as Error).message}`);\n return composeCoreOnly(manifests);\n }\n}\n\nfunction isServerRendered(): boolean {\n if (document.documentElement.hasAttribute(\"data-everything-ssr\")) {\n return true;\n }\n if (window.__EVERYTHING_DEV_SSR__ !== undefined) {\n return window.__EVERYTHING_DEV_SSR__;\n }\n return window.$_TSR !== undefined;\n}\n\nfunction watchHydrationConsumed() {\n const bootstrapWatch = setInterval(() => {\n if (window.$_TSR === undefined) {\n clearInterval(bootstrapWatch);\n mark(\"hydration consumed ($_TSR deleted — h() ran)\");\n }\n }, 50);\n}\n\nexport async function hydrate(options: CoreHydrateOptions) {\n if (window.__EVERYTHING_DEV_HYDRATE_PROMISE__) {\n return window.__EVERYTHING_DEV_HYDRATE_PROMISE__;\n }\n\n const hydratePromise = (async () => {\n console.log(\"[Hydrate] Starting...\");\n\n const runtimeConfig = options.config ?? getRuntimeConfig();\n const cspNonce = getCspNonce();\n\n if (!runtimeConfig.hostUrl || !runtimeConfig.rpcBase) {\n throw new Error(\"Missing hostUrl or rpcBase in runtime config\");\n }\n\n const [{ QueryClientProvider }, routerFactory] = await Promise.all([\n import(\"@tanstack/react-query\"),\n options.createRouter\n ? Promise.resolve(options.createRouter)\n : import(\"./router-client\").then((m) => m.createRouter as AppRouterFactory),\n ]);\n const coreRouteConfig = await options\n .routeConfig()\n .then((mod) => (\"default\" in mod ? mod.default : mod));\n const coreManifest = options.manifest\n ? await options\n .manifest()\n .then((raw) =>\n typeof raw === \"object\" && raw !== null && \"default\" in raw\n ? (raw as { default: unknown }).default\n : raw,\n )\n .then((raw) => parsePluginManifest(raw))\n : undefined;\n const client = options.createQueryClient?.() ?? defaultQueryClient();\n\n mark(`$_TSR present: ${Boolean(window.$_TSR)}`);\n\n const composed = await composeFromPayload(runtimeConfig, coreRouteConfig, coreManifest);\n\n const { router, queryClient: builtClient } = routerFactory({\n routeTree: composed?.routeTree,\n context: {\n pluginNav: composed?.nav,\n queryClient: client,\n runtimeConfig,\n cspNonce,\n locale: isServerRendered() ? document.documentElement.lang : undefined,\n apiClient: createApiClient({\n hostUrl: runtimeConfig.hostUrl,\n rpcBase: runtimeConfig.rpcBase,\n connectionError: options.apiConnectionError,\n }),\n authClient: createAuthClient({ runtimeConfig, cspNonce }),\n },\n });\n const providerClient = builtClient ?? client;\n\n // A server-rendered page whose compose degraded to core-only would\n // hydrate a DIFFERENT tree than the HTML contains — a guaranteed React\n // hydration failure. Client-render cleanly instead; hydration is only\n // safe when the composed tree is the one the server rendered.\n const canHydrate = isServerRendered() && Boolean(composed) && !composed!.degraded;\n\n if (canHydrate) {\n const { hydrateRoot } = await import(\"react-dom/client\");\n const { RouterClient } = await import(\"@tanstack/react-router/ssr/client\");\n\n console.log(\"[Hydrate] Calling hydrateRoot...\");\n hydrateRoot(\n document,\n <QueryClientProvider client={providerClient}>\n <RouterClient router={router} />\n </QueryClientProvider>,\n );\n watchHydrationConsumed();\n } else {\n const { createRoot } = await import(\"react-dom/client\");\n const { RouterProvider } = await import(\"@tanstack/react-router\");\n\n console.log(\"[Hydrate] Calling createRoot...\");\n createRoot(document).render(\n <QueryClientProvider client={providerClient}>\n <RouterProvider router={router} />\n </QueryClientProvider>,\n );\n }\n\n if (composed?.degraded) {\n const { toast } = await import(\"sonner\");\n toast.error(\"Some application features couldn't load\", {\n id: \"application-compose-error\",\n description: \"Plugin pages are unavailable. Reload to try again.\",\n duration: Number.POSITIVE_INFINITY,\n action: { label: \"Reload\", onClick: () => window.location.reload() },\n });\n }\n\n console.log(\"[Hydrate] Complete!\");\n })().catch((error) => {\n console.error(\"[Hydrate] Failed:\", error);\n window.__EVERYTHING_DEV_HYDRATE_PROMISE__ = undefined;\n const message = document.createElement(\"main\");\n message.setAttribute(\"role\", \"alert\");\n message.dataset.testid = \"application-startup-error\";\n message.className =\n \"min-h-screen flex flex-col items-center justify-center gap-4 bg-background text-foreground p-6\";\n const heading = document.createElement(\"h1\");\n heading.textContent = \"The application couldn't load\";\n const detail = document.createElement(\"p\");\n detail.textContent = \"Check your connection and reload to try again.\";\n const retry = document.createElement(\"button\");\n retry.textContent = \"Reload\";\n retry.className = \"rounded-md border border-border px-4 py-2\";\n retry.addEventListener(\"click\", () => window.location.reload());\n message.append(heading, detail, retry);\n document.body.replaceChildren(message);\n throw error;\n });\n\n window.__EVERYTHING_DEV_HYDRATE_PROMISE__ = hydratePromise;\n return hydratePromise;\n}\n\nexport default hydrate;\n"],"mappings":"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"}