NextJS 中使用 fetch 请求时,默认的缓存方式是 { cache: 'force-cache' }, 也就是说所有的默认请求都会被缓存,并应用 请求记忆功能,在跨路由使用相同的请求数据时,不必在路由顶部获取数据,而是可以在任意组件中获取数据,因为请求已经缓存,所以多次调用只会发送一次,而不必担心通过网络对同一数据进行多次请求对性能的影响。

但是根据在控制台的观察发现,请求的缓存状态为 (cache skip), 表示跳过了缓存,没有命中,如果是命中了缓存的话应该是 (cache hit)

动态 API 导致缓存失效

排查发现造成这一现象的原因是因为使用了动态 API ,将渲染变成了动态渲染,不会再有缓存,在 NextJS 的动态API有下面这些动态API

如果你的请求是在调用这些 API 之后发出的,那么缓存功能就会失效,在我的项目中,失效的原因在于发送请求之前,从 cookie().get() 中获取了用户请求的 token,然后将 token 设置在了对后端 API的请求头里,导致缓存失效

其他影响缓存的因素

  • App Router 中,fetch 的缓存行为取决于路由段的静态/动态性质
    • app/blog/[slug]/page.tsx
    • app/dashboard/page.tsx?search=query
  • 这些配置都会使路由变成动态的,从而禁用默认缓存
  • export const dynamic = 'force-dynamic'
  • export const revalidate = 0
  • export const dynamicParams = true

优化两套 Request 的方法

为了实现在服务器组件和客户端组件发送 fetch 请求,封装了两个单独的 request 方法,原因是因为需要获取 cookie 中的 token,然后设置到请求 header 上,在服务器组件中只能从 cookie() 方法中获取,它是一个仅在服务器上运行的 API,在客户端上无法调用这个 API,在客户端上,我们使用 document.cookie 获取 token

这个问题是否有解决的办法?

如果后端不从 Header 中获取 token,而是设置 cookiehttponly,然后请求时自动携带 cookie 发送给后端,后端从 cookie 中自己获取 token 来验证用户权限,这样是否能解决?

参考

双链