菜单

战争迷雾与惰性加载

相关源文件

本文档解释了 React Router 的“战争迷雾”路由发现机制和延迟加载功能。这些功能通过按需渐进式加载路由及其关联代码,而不是一次性加载,来优化应用程序性能。有关数据加载策略的更多信息,请参阅 数据 API,有关服务器端渲染的详细信息,请参阅 服务器端渲染

战争迷雾概念

战争迷雾(也称为“延迟路由发现”)是一种源自游戏的概念,即未探索的区域在访问前保持隐藏状态。在 React Router 中,这个概念适用于那些最初未加载,但在导航过程中动态发现的路由。

来源

战争迷雾工作原理

  1. 初始加载:应用程序加载时只包含必要的路由(通常只有当前路由及其父路由)
  2. 路由发现:当用户导航到之前未发现的路由时,React Router 会
    • 拦截导航请求
    • 通过 /__manifest 端点从服务器请求路由信息
    • 将新路由添加到路由树
    • 完成导航

此过程由在路由初始化期间配置的 patchRoutesOnNavigation 函数处理。

来源

React Router 通过链接控制路由的发现时机

发现行为选项有

  • “render”(默认):渲染链接时发现路由
  • “none”:不主动发现,仅在链接被点击时发现

来源

延迟加载

延迟加载通过允许按需加载路由组件和数据处理程序来补充战争迷雾。这实现了路由级别的代码分割。

两种延迟加载方法

React Router 支持两种延迟加载路由模块的语法方法

1. 延迟函数方法

2. 延迟对象方法(v7.5.0 中添加)

基于对象的方法提供了对代码分割的更细粒度控制,对性能敏感的应用程序特别有用。

来源

对象 API 的优势

v7.5.0 中引入的对象 API 提供了多项优势

  1. 更好的代码分割:每个路由属性都可以从单独的文件导入
  2. 性能优化:仅加载必要的代码块
  3. 框架兼容性:对框架模式和库模式应用程序提供更好的支持
  4. 优化后的水合:在水合后延迟加载路由时,会跳过 HydrateFallback 等属性

来源

战争迷雾实现细节

Manifest 请求机制

当战争迷雾激活时,React Router 会向 /__manifest 端点发起请求以发现路由

GET /__manifest?p=/parent/child&version=abc123

服务器会响应请求路径以及可能包含索引路由的任何父路径的路由定义。

来源

版本处理和 Manifest 偏差

React Router 包含检测和处理“Manifest 偏差”的机制,即客户端和服务器路由 Manifest 不一致的情况(通常在新部署后)

  1. 版本标识符包含在 Manifest 请求中
  2. 当服务器检测到版本不匹配时,它会响应 204 状态码
  3. React Router 随后会触发整页刷新以获取最新版本

这有助于防止用户在部署后使用过时的路由定义进行导航时出现问题。

来源

渐进式路由发现

React Router 包含一项优化,可自动发现视口内的路由

  1. 一个 MutationObserver 监视带有 data-discover 属性的新链接
  2. 发现的链接会被添加到队列中以进行 Manifest 获取
  3. 路由以批次预取,以避免过多的网络请求
  4. 去重机制可防止已发现的路由被重复获取

这种渐进式发现方法通过在路由即将需要时加载它们,确保了最佳性能。

来源

与其他系统集成

服务器端渲染 (SSR)

战争迷雾旨在与服务器端渲染协同工作

  1. 服务器渲染初始路由并生成部分 Manifest
  2. 在水合过程中,React Router 使用此部分 Manifest
  3. 其他路由在客户端导航期间被渐进式发现

ssr: false(SPA 模式)时,战争迷雾仍然有效,但工作方式不同

  • 仅渲染根路由
  • 所有路由发现都在客户端进行

来源

预渲染

战争迷雾可与预渲染结合使用,以优化静态站点生成

  1. 静态路由在构建时进行预渲染
  2. 运行时,应用程序可以发现超出预渲染范围的动态路由
  3. 对于预渲染的路由,数据可以从静态 .data 文件加载

来源

单次获取策略

战争迷雾与 React Router 的 Single Fetch 数据加载策略集成

  1. 导航过程中,发现的路由会包含在数据获取中
  2. 单个网络请求加载路由定义及其数据
  3. 对于客户端加载器/操作,会发出单独的请求来延迟加载数据

此集成确保了动态发现路由的高效数据加载。

来源

最佳实践

  1. 路由组织:将路由组织成逻辑层级,以受益于“战争迷雾”的渐进式加载
  2. 代码分割:使用基于对象的懒加载 API 将路由组件、加载器和操作分割成单独的块
  3. 预取控制:使用发现和预取行为来优化路由加载时间
  4. 错误处理:实现适当的错误边界来处理路由加载失败
  5. 版本管理:使用内置的版本检查来安全地处理部署

来源

何时使用

“战争迷雾”和懒加载最适用于

  1. 拥有大量路由的大型应用程序
  2. 用户通常只访问部分路由的应用程序
  3. 路由组件或数据处理程序加载成本高昂的应用程序
  4. 优先考虑初始加载性能的渐进式 Web 应用程序

对于路由很少的小型应用程序,“战争迷雾”的开销可能不值得。

来源