菜单

服务器端渲染

相关源文件

React Router 的服务器端渲染 (SSR) 允许在将 HTML 发送到客户端之前在服务器上渲染 React 组件。本文档解释了 React Router 的 SSR 架构、数据加载策略、水合(hydration)过程以及“迷雾”(Fog of War)路由发现等高级功能。有关平台特定服务器集成的信息,请参阅 平台适配

React Router 中的 SSR 概述

React Router 的服务器端渲染系统允许您的应用程序

  1. 在服务器上渲染初始 HTML
  2. 并行加载路由加载器 (route loaders) 的数据
  3. 将完整的 HTML 文档发送到客户端
  4. 在客户端进行应用程序的水合(hydration)以实现交互性

该框架处理服务器与客户端之间的协调、数据获取管理以及从服务器渲染的 HTML 到交互式客户端应用程序的平滑过渡的复杂性。

来源

SSR 架构

React Router 的 SSR 架构涉及多个关键组件在服务器和客户端环境中协同工作。

服务器端渲染过程从由 createRequestHandler 处理的 HTTP 请求开始,该函数确定请求的类型并进行相应处理。文档请求会渲染完整的 HTML 文档,而数据请求则获取路由加载器的数据。然后客户端对服务器渲染的 HTML 进行水合(hydration),以创建交互式应用程序。

来源

服务器请求处理程序

React Router 的 SSR 核心是 createRequestHandler 函数,该函数处理传入的 HTTP 请求。

请求处理程序

  1. 处理传入的 HTTP 请求
  2. 将请求与路由匹配
  3. 处理文档、数据和资源请求
  4. 管理服务器渲染过程中的错误
  5. 返回相应的 HTTP 响应

创建服务器处理程序

createRequestHandler 函数接受一个 ServerBuild 对象,其中包含您的路由和应用程序配置。

此函数返回一个请求处理程序,可与 Node.js、Express、Cloudflare Workers 或其他服务器环境一起使用。

来源

通过“单次抓取”(Single Fetch)进行数据加载

React Router 为服务器端渲染实现了一种优化的数据加载策略,称为“单次抓取”(Single Fetch)。

单次抓取策略

  1. 批量加载器调用:不是为每个路由加载器发出单独的请求,而是在一次调用中完成所有加载器。
  2. 最小化瀑布流:防止顺序数据加载,避免减慢渲染过程。
  3. 优化带宽:减少数据所需的 HTTP 请求数量。

来源

实现细节

单次抓取策略通过几个函数实现:

  • getSingleFetchDataStrategy:创建用于优化数据加载的数据策略函数。
  • singleFetchLoaderNavigationStrategy:处理导航的数据加载。
  • singleFetchLoaderFetcherStrategy:处理 fetchers 的数据加载。
  • singleFetchActionStrategy:处理表单提交和其他操作。

来源

注水过程

水合(Hydration)是将服务器渲染的 HTML 通过附加事件监听器和 React 状态变为交互式组件的过程。

在水合过程中

  1. 服务器会将关键状态数据包含在 HTML 响应中。
  2. 客户端会解码这些数据来初始化路由器。
  3. React 会“水合”DOM 节点,保留服务器渲染的 HTML。
  4. 组件在水合完成后变得完全交互。

水合状态

HydrationState 类型代表从服务器传递到客户端的数据。

这包括:

  • loaderData:由路由加载器加载的数据。
  • actionData:表单操作的结果。
  • errors:渲染过程中遇到的任何错误。

来源

HydrateFallback(水合回退)

React Router 提供了一个 HydrateFallback 组件,该组件在客户端水合过程中显示。这个组件允许您在完整的交互式组件就绪之前显示一个轻量级的加载状态。

来源

战争迷雾与惰性加载

React Router 在服务器端渲染期间实现了“迷雾”(Fog of War)方法来进行路由发现和懒加载。

迷雾(Fog of War)提供:

  1. 渐进式路由加载:只将初始匹配的路由发送到客户端。
  2. 按需发现:当用户导航到某个路由时,会加载额外的路由。
  3. 带宽优化:减少初始 JavaScript 负载大小。
  4. 改进的性能:通过仅发送必要的代码来加快初始加载速度。

迷雾(Fog of War)的工作原理

  1. 服务器只渲染最初匹配的路由。
  2. 客户端通过 /__manifest 端点按需请求其他路由。
  3. 服务器提供路由补丁(route patches),这些补丁会被动态应用于客户端路由器。

来源

SSR 与 SPA 模式

React Router 支持服务器端渲染 (SSR) 和单页应用 (SPA) 模式。

功能SSR 模式SPA 模式
初始渲染服务器仅客户端
数据加载服务器和客户端仅客户端
搜索引擎优化优化有限
初始加载性能通常更快初始加载较慢
路由加载器在服务器上运行仅在客户端运行
构建配置ssr: truessr: false

SPA 模式下的预渲染

React Router 还支持在使用 SPA 模式处理动态路由的同时,预渲染静态路由。

这种混合方法允许您:

  1. 预渲染已知路由以获得更好的 SEO 和初始加载性能。
  2. 为动态路由回退到客户端渲染。
  3. 利用 SSR 和 SPA 模式的双重优势。

来源

处理服务器端错误

React Router 在服务器端渲染期间提供了强大的错误处理功能。

当服务器渲染过程中发生错误时:

  1. 错误会被捕获并进行清理(生产环境中会移除敏感信息)。
  2. 最接近的错误边界(error boundary)会渲染错误 UI。
  3. 错误信息会被包含在初始状态中。
  4. 客户端会使用此错误状态进行水合,并显示错误 UI。

ErrorBoundary 组件

路由可以定义一个 ErrorBoundary 组件,该组件负责在发生错误时进行渲染。

来源

与服务器环境集成

React Router 的 SSR 功能可以通过平台适配集成到各种服务器环境中。

React Router 提供了各种平台适配,用于集成 Node.js、Express 和 Cloudflare Workers 等不同服务器环境。有关这些集成的详细信息,请参阅 平台适配

来源

性能考量

React Router 的服务器端渲染 (SSR) 功能提供了多种性能优势,但也伴随着一些需要考虑的因素。

方面优点考量因素
首次字节时间 (TTFB)由于服务器处理,可能较慢初始 HTML 包含内容
首次内容绘制时间 (FCP)由于内容包含在初始 HTML 中,所以更快服务器必须在发送响应之前完成所有渲染
可交互时间 (TTI)FCP 和 TTI 之间的差距通常更长客户端必须在可交互之前下载并执行 JavaScript
数据加载消除了客户端数据获取的瀑布效应服务器必须在响应之前获取所有数据
打包大小通过代码分割和“战争迷雾”可以做得更小数据水合 (Hydration) 需要 JavaScript 来处理可交互组件

优化技术

  1. 使用“战争迷雾” (Fog of War):启用渐进式路由加载,以减少初始 JavaScript 有效负载。
  2. 实现局部数据水合 (Partial Hydration):仅对需要交互的页面部分进行选择性数据水合。
  3. 配置预渲染 (Prerendering):在为动态路由使用 SPA 模式的同时,预渲染静态路由。
  4. 利用单一数据获取 (Single Fetch):使用内置的单一数据获取策略来优化数据加载。

来源

结论

React Router 的服务器端渲染功能提供了一个强大的解决方案,用于构建高性能和对 SEO 友好的应用程序。通过将 SSR 与诸如单一数据获取 (Single Fetch) 和诸如“战争迷雾” (Fog of War) 的渐进式加载技术相结合,React Router 能够实现高效的服务器渲染应用程序,并使其能够顺利地过渡到客户端交互。

该框架的灵活架构能够适应各种服务器环境,并支持完全 SSR 和带预渲染的混合方法。了解 SSR 流程、数据水合流程和优化技术将帮助您构建高效的应用程序,并提供最佳的用户体验。