在 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
,而是设置cookie
的httponly
,然后请求时自动携带cookie
发送给后端,后端从cookie
中自己获取token
来验证用户权限,这样是否能解决?
参考
- cookies break caching/memoization · Issue #58288 · vercel/next.js · GitHub
- next.config.js Options: serverComponentsHmrCache | Next.js
- Rendering: Server Components | Next.js