Next.js 通过缓存渲染工作和数据请求来提升应用性能并降低成本
这篇文章发布于 2025年08月29日,星期五,08:38。阅读 ? 次,? 条评论
启用 cacheComponents 新标志时(默认不缓存),以下绝大部分内容概念已被抛弃
以下是不同缓存机制及其用途的概述:
| 名称 | 是什么 | 在哪里 | 目的 | 生命周期 |
|---|---|---|---|---|
| Request Memoization | 函数的返回值 | 服务器 | 在 React 组件树中重用数据 | 每个请求的生命周期 |
| Data Cache | 数据 | 服务器 | 跨用户请求和部署存储数据 | 持久性(可重新验证) |
| Full Route Cache | HTML 和 RSC 有效载荷 | 服务器 | 降低渲染成本并提高性能 | 持久性(可重新验证) |
| Router Cache | RSC 有效载荷 | 客户 | 减少导航时的服务器请求 | 用户会话或基于时间 |
默认情况下,Next.js 会尽可能多地缓存,以提高性能并降低成本。这意味着路由会被静态渲染 ,并且数据请求也会被缓存 ,除非您选择退出。
middleware 不支持获取缓存。任何在 middleware 内部执行的获取操作都将被取消缓存。
Next.js 扩展了 fetch API ,可以自动记忆具有相同 URL 和选项的请求。这意味着你可以在 React 组件树的多个位置针对同一数据调用 fetch 函数,而不必担心通过网络对同一数据进行多次请求所带来的性能影响。
MISSHIT,数据将从内存中返回,而无需执行该函数fetch 请求中的 GET 方法generateMetadata 、 generateStaticParams 、Layouts、Pages 和其他服务器组件中的 fetch 请求fetch 请求,因为它们不是 React 组件树的一部分fetch 的情况(例如某些数据库客户端、CMS 客户端或 GraphQL 客户端),您可以使用 React cache 功能来记忆函数缓存持续服务器请求的整个生命周期,直到 React 组件树完成渲染
由于记忆不会在服务器请求之间共享并且仅在渲染期间适用,因此无需重新验证它
Next.js 具有内置数据缓存,可持久保存传入服务器请求和部署的数据提取结果。这是因为 Next.js 扩展了原生的 fetch API,允许服务器上的每个请求设置自己的持久缓存语义。
'force-cache' 选项的 fetch 请求时,Next.js 会检查数据缓存中是否有缓存的响应cache 选项或使用 { cache: 'no-store' } ),结果始终从数据源获取并记忆虽然两种缓存机制都可以通过重复使用缓存数据来提高性能,但数据缓存在传入的请求和部署中是持久的,而记忆仅持续请求的整个生命周期
除非您重新验证或选择退出,否则数据缓存将在传入请求和部署中持续存在
可以通过两种方式重新验证缓存数据:
基于时间的重新验证:经过一段时间并发出新请求后重新验证数据。这对于不频繁更改且新鲜度不太重要的数据非常有用。
要按时间间隔重新验证数据,您可以使用 fetch 的 next.revalidate 选项来设置资源的缓存寿命(以秒为单位)
fetch('https://...', { next: { revalidate: 3600 } })或者,您可以使用路由段配置选项来配置段中的所有 fetch 请求,或者在您无法使用 fetch 情况下使用
const dynamic = 'force-dynamic'
const fetchCache = 'default-no-store'revalidate 的获取请求时,数据将从外部数据源获取并存储在数据缓存中Next.js 会在构建时自动渲染并缓存路由。这是一种优化,允许您使用缓存的路由,而不是每次请求都重新在服务器上渲染,从而提高页面加载速度
React 服务器组件负载是已渲染的 React 服务器组件树的紧凑二进制表示。React 在客户端使用它来更新浏览器的 DOM。React 服务器组件负载包含:
路由在构建时是否缓存取决于它是静态渲染还是动态渲染。静态路由默认会被缓存,而动态路由在请求时渲染,不会被缓存
默认情况下,完整路由缓存是持久性的。这意味着渲染输出会在用户请求之间进行缓存
您可以选择退出完整路由缓存,或者换句话说,为每个传入请求动态渲染组件,方式如下:
dynamic = 'force-dynamic' 或 revalidate = 0 路由段配置选项:这将跳过完整路由缓存和数据缓存。这意味着每次向服务器发出请求时,组件都会被渲染并获取数据。由于路由器缓存是客户端缓存,因此它仍然有效fetch 请求,则该路由将退出完整路由缓存。每次收到请求时,都会获取该 fetch 请求对应的数据。其他明确启用缓存的 fetch 请求仍将缓存在数据缓存中。这允许混合缓存和非缓存数据Next.js 有一个内存客户端路由器缓存,用于存储路由段的 RSC 有效负载,按布局、加载状态和页面拆分
当用户在路由之间导航时,Next.js 会缓存已访问的路由段,并预取用户可能导航到的路由。这样可以实现即时的前进/后退导航,导航之间无需重新加载整个页面,并且在共享布局中保留浏览器状态和 React 状态
缓存存储在浏览器的临时内存中。路由器缓存的持续时间由两个因素决定:
prefetch={null} 或未指定):动态页面不缓存,静态页面缓存 5 分钟prefetch={true} 或 router.prefetch):静态和动态页面都需要 5 分钟虽然页面刷新将清除所有缓存的段,但自动失效期仅影响从预取时起的单个段
revalidatePath 或通过缓存标签 revalidateTag 按需重新验证数据cookies.set 或 cookies.delete 会使路由器缓存无效,以防止使用 cookie 的路由变得陈旧(例如身份验证)router.refresh 将使路由器缓存无效,并向服务器发出当前路由的新请求按需重新验证: 根据事件(例如表单提交)重新验证数据。按需重新验证可以使用基于标签 revalidateTag 或基于路径 revalidatePath 的方法一次性重新验证多组数据。当您希望确保尽快显示最新数据时(例如,当您的无头 CMS 中的内容更新时),此功能非常有用
fetch 请求时,数据将从外部数据源获取并存储在数据缓存中MISS ,会从外部数据源中获取数据,存放到 Data Cache 中