diff --git a/contributors.yml b/contributors.yml
index 7f8e26b2fa..85fcf53325 100644
--- a/contributors.yml
+++ b/contributors.yml
@@ -448,3 +448,4 @@
- zeromask1337
- zheng-chuang
- zxTomw
+- uozer7050
diff --git a/packages/react-router/lib/dom/ssr/components.tsx b/packages/react-router/lib/dom/ssr/components.tsx
index 318fa0bf51..e681c7669d 100644
--- a/packages/react-router/lib/dom/ssr/components.tsx
+++ b/packages/react-router/lib/dom/ssr/components.tsx
@@ -256,13 +256,20 @@ export interface LinksProps {
* @returns A collection of React elements for [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
* tags
*/
+// Persistent set of hrefs so that CSS/JS links are not removed when
+// routes unmount. This ensures lazy-loaded CSS persists across route changes.
+const persistentHrefs = new Set();
+
export function Links({ nonce }: LinksProps): React.JSX.Element {
let { isSpaMode, manifest, routeModules, criticalCss } =
useFrameworkContext();
let { errors, matches: routerMatches } = useDataRouterStateContext();
+ // Get the active route matches (slice matches on error boundaries, etc.)
let matches = getActiveMatches(routerMatches, errors, isSpaMode);
+ // Compute the keyed links for all active matches. These include CSS modules,
+ // prefetch links, and other assets. Memoized to avoid unnecessary recalculations.
let keyedLinks = React.useMemo(
() => getKeyedLinksForMatches(matches, routeModules, manifest),
[matches, routeModules, manifest],
@@ -270,12 +277,15 @@ export function Links({ nonce }: LinksProps): React.JSX.Element {
return (
<>
+ {/* Inject critical CSS as