前言
众所周知,React Router
原本是为 客户端渲染(CSR)
和 客户端导航
设计的,它依赖 useLocation
、useNavigate
、useParams
等 Hook
来获取/改变路由状态。同时,服务端组件
不能访问 window
、history
、location
等 浏览器 API
。
这就导致一直以来 React Router
无法被 SRC
时使用,但是这种情况从今天开始发生了改变。
本文将介绍 React Router
如何通过 Framework Mode
和 RSC
支持解决这些问题,以及 Framework Mode
的底层原理。
往期精彩推荐
- 🚀🚀🚀 Prettier 3.6.0 正式发布,支持 OXC⚓️、Hermes !更快的体验⚡️
- 🚀🚀🚀Prisma ORM 6.10.0 重大更新,VSCode 集成,远程 MCP ,更加智能了!
- 🚀🚀🚀恭喜 Rolldown 获得 JS 开源奖年度突破奖,2025 年 JS 开源奖典礼回顾!🎉🎉🎉
- 更多精彩文章欢迎关注我的公众号:萌萌哒草头将军
正文
服务器端 React
的三大挑战
在服务器端渲染 React
应用时,开发者面临以下三个主要挑战:
- 数据内联(
Inlining Data
) :如何高效地将服务器端的数据传递到浏览器中的React
组件,同时保持性能和开发效率。 - UI流式传输(
Streaming UI
) :如何确保用户在所有数据加载完成之前就能看到部分UI
,从而提升用户体验。 - 路由代码分割(
Code Splitting Routes
):如何避免在首次页面加载时下载整个应用的代码,以减少加载时间。
这些挑战直接影响了应用的性能、用户体验和开发复杂度。React Router
通过其 Framework Mode
和 RSC
支持提供了灵活的解决方案,下面我们逐一分析。
如何解决这些挑战
1. 数据内联
挑战 :在服务器端渲染中,数据需要从服务器高效传递到浏览器中的 React
组件。如果处理不当,可能导致性能瓶颈或复杂的代码逻辑。
解决方案:
- Framework Mode :
React Router
通过loader
函数实现数据内联。开发者可以在路由中定义loader
函数,这些函数在服务器端执行并返回数据。React Router
随后通过useLoaderData()
钩子将数据传递给对应的组件。例如:
javascript
export async function loader() {
return fetchDataFromServer();
}
function Component() {
const data = useLoaderData();
return <div>{data.title}</div>;
}
这种方式简化了数据管理,开发者无需手动处理数据传递的复杂逻辑。
-
React RSC :
RSC
通过从服务器组件
直接向"use client"
组件传递props
来实现数据内联。服务器组件
在服务器端执行逻辑,将数据作为props
传递给客户端组件
。这种方法减少了客户端的JavaScript
负担,提高了性能。 -
React Router RSC Support :
React Router
支持两种数据内联方式,开发者可以根据项目需求选择Framework Mode
的loader
函数或RSC
的props
传递方式。这种灵活性确保了新老项目都能无缝集成。
2. UI流式传输
挑战:在服务器端渲染中,如果用户需要等待所有数据加载完成才能看到页面,可能会导致较差的用户体验,例如长时间的空白页面或加载指示器。
解决方案:
- Framework Mode :
React Router
通过loader
函数返回promises
,结合React
的<Suspense>
和<Await>
组件实现UI
流式传输。开发者可以为<Suspense>
指定fallback
内容,在数据加载期间显示占位UI
。例如:
javascript
function Component() {
const data = useLoaderData();
return (
<Suspense fallback={<div>加载中...</div>}>
<Await resolve={data.promise}>
{(resolvedData) => <div>{resolvedData.title}</div>}
</Await>
</Suspense>
);
}
这种方式让用户在数据加载期间看到部分 UI
,提升了交互体验。
-
React RSC :
RSC
通过将promises
作为props
传递,在服务器端
使用await
处理异步数据,在客户端
使用use(promise)
钩子。这种方法同样支持UI
的逐步渲染,减少了用户的等待时间。 -
React Router RSC Support :
React Router
支持两种流式传输模式,开发者可以根据项目需求选择Framework Mode
的Suspense
机制或RSC
的异步处理方式。这种兼容性为开发者提供了更大的灵活性。
3. 路由代码分割
挑战 :在传统的单页面应用(SPA
)中,首次加载时浏览器可能需要下载整个应用的代码,这对于大型应用来说会导致较长的加载时间。
解决方案:
Framework Mode
:通过routes.ts
配置文件,结合捆绑器插件(如Vite
),React Router
生成一个清单(manifest
),将路由映射到对应的代码块(chunks
)。浏览器只需下载当前路由所需的代码块。例如:
javascript
// routes.ts
export default [
{ path: "/", component: "./Home.tsx" },
{ path: "/about", component: "./About.tsx" },
];
捆绑器插件会根据此配置生成代码块,确保高效加载。
-
React RSC
:RSC
通过在服务器端
使用动态导入(dynamic imports
)和"use client"
指令,确保浏览器只下载当前路由所需的代码。这种方法无需额外的配置文件,直接在应用代码中定义路由。 -
React Router RSC Support
:React Router
提供了一种更简单的架构,路由直接在应用代码中定义,无需routes.ts
或捆绑器插件。这种方式减少了配置复杂性,使开发者更容易管理和扩展应用。
Framework Mode
的底层原理
Framework Mode
是 React Router
的一种高级模式,通过高度抽象化简化了 服务器端渲染
和 数据加载
的复杂性。其底层原理包括以下几个关键部分:
机制 | 描述 |
---|---|
路由配置 | 通过 routes.ts 文件定义路由结构,捆绑器插件(如 Vite )处理该文件,生成路由到代码块的映射。 |
数据加载 | 每个路由可定义 loader 函数,在 服务器端 执行并返回数据,React Router 自动将数据传递给组件。 |
代码分割 | 捆绑器插件根据 routes.ts 生成清单(manifest ),指导浏览器加载当前路由所需的代码块。 |
流式传输 | 支持 loader 函数返回 promises ,结合 React 的 Suspense 机制,实现 UI 的流式传输,开发者可定义 fallback 内容。 |
这些机制的核心在于将复杂的 服务器端渲染
过程封装在 React Router
和捆绑器插件中。开发者只需定义路由和 loader
函数,React Router
负责处理数据传递、代码分割和 UI
渲染的细节。例如,捆绑器插件会自动生成 清单文件
,确保浏览器只加载必要的代码块,而 Suspense
机制则通过 fallback
内容优化用户体验。
这种抽象让开发者可以专注于业务逻辑,而无需深入理解底层的 服务器端渲染
和数据流机制。Framework Mode
的强大之处在于它与捆绑器(如 Vite
)的紧密集成,处理了代码分割和清单生成的复杂细节,使得开发过程更加顺畅。
最后
React Router
与 RSC
的结合标志着 Web
开发的一个重要里程碑。通过解决 数据内联
、UI流式传输
和 路由代码分割
三大挑战,React Router
为开发者提供了灵活且高效的工具!
今天的分享就这些了,感谢大家的阅读,如果文章中存在错误的地方欢迎指正!