UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

104 lines (84 loc) 3.09 kB
import { isWebClient } from '../constants' import type { OneRouter } from '../interfaces/router' import { evictOldest } from '../utils/evictOldest' import { getLinkingConfig as createLinkingConfig, type OneLinkingOptions, } from './getLinkingConfig' import type { RouteNode } from './Route' let linkingConfig: OneLinkingOptions | undefined // cache the base linking config (route-tree dependent, not URL-dependent) let cachedBaseLinkingConfig: OneLinkingOptions | undefined let cachedRouteNodeForLinking: RouteNode | null = null // cache getStateFromPath results by path for SSR performance // same path always produces the same navigation state (route tree is static in prod) const ssrStateCache = new Map<string, OneRouter.ResultState | undefined>() export function getLinking() { return linkingConfig } export function setLinking(_: OneLinkingOptions) { linkingConfig = _ } export function resetLinking() { linkingConfig = undefined } /** * Ensure the base linking config is initialized for a given route tree. * Does not set any per-request state. */ export function ensureBaseLinkingConfig(routeNode: RouteNode | null) { if ( routeNode && (routeNode !== cachedRouteNodeForLinking || !cachedBaseLinkingConfig) ) { cachedBaseLinkingConfig = createLinkingConfig(routeNode) cachedRouteNodeForLinking = routeNode } } /** * Compute initialState from a URL path, with caching for SSR. * Does not modify the global linkingConfig. */ export function getSSRInitialState( routeNode: RouteNode | null, initialLocation: URL ): OneRouter.ResultState | undefined { if (!routeNode) return undefined ensureBaseLinkingConfig(routeNode) if (!cachedBaseLinkingConfig) return undefined const path = initialLocation.pathname + (initialLocation.search || '') if (ssrStateCache.has(path)) return ssrStateCache.get(path) const state = cachedBaseLinkingConfig.getStateFromPath?.( path, cachedBaseLinkingConfig.config ) evictOldest(ssrStateCache, 5000, 1000) ssrStateCache.set(path, state) return state } export function setupLinking( routeNode: RouteNode | null, initialLocation?: URL ): OneRouter.ResultState | undefined { let initialState: OneRouter.ResultState | undefined if (routeNode) { // reuse ensureBaseLinkingConfig to avoid duplicating cache logic ensureBaseLinkingConfig(routeNode) // shallow copy so per-request mutations (getInitialURL) don't affect cache linkingConfig = { ...cachedBaseLinkingConfig! } if (initialLocation) { linkingConfig.getInitialURL = () => initialLocation.toString() let path = initialLocation.pathname + (initialLocation.search || '') if (isWebClient) { const historyState = window.history.state if (historyState?.__tempLocation?.pathname && !historyState.__tempKey) { path = historyState.__tempLocation.pathname + (historyState.__tempLocation.search || '') } } initialState = linkingConfig.getStateFromPath?.(path, linkingConfig.config) } } return initialState }