前言
众所周知,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 为开发者提供了灵活且高效的工具!
今天的分享就这些了,感谢大家的阅读,如果文章中存在错误的地方欢迎指正!