Next.js 13构建时fetch被调用两次及静态页面数据变更问题
Next.js 13 fetch缓存相关问题解答
问题场景
使用Next.js 13的fetch并配置{cache:'force-cache'}调用随机笑话API时,构建过程中fetch被调用两次,且静态生成的页面点击刷新按钮后数据发生变化。
代码示例
// page.js import {RefreshButton} from './RefreshButton' async function getRandomJoke(){ const res = await fetch("https://v2.jokeapi.dev/joke/Programming?type=single", {cache:'force-cache'}) const data = await res.json() console.log("fetch called. Joke is: ", data['joke']) return data['joke'] } export default async function Home() { const joke = await getRandomJoke() return ( <div> {joke} <RefreshButton/> </div> ) }
构建日志
[= ] info - Generating static pages (2/3)fetch called. Joke is: A programmer puts two glasses on his bedside table before going to sleep. A full one, in case he gets thirsty, and an empty one, in case he doesn't. [== ] info - Generating static pages (2/3)fetch called. Joke is: The generation of random numbers is too important to be left to chance.
核心问题
- 为何构建时
fetch会被调用两次? - 静态生成的页面刷新后数据为何会发生变化?
问题解答
1. 构建时fetch两次调用的原因
Next.js 13在静态生成(SSG)阶段存在两次渲染流程:
- 第一次是数据收集阶段:Next.js会执行组件以识别所有数据依赖(比如
fetch调用),此时会触发getRandomJoke函数执行一次fetch。 - 第二次是正式静态页面生成阶段:基于收集到的依赖,再次执行组件生成最终的静态HTML内容,这会再次触发
fetch调用。
虽然配置了{cache:'force-cache'},但在静态构建的这两次渲染过程中,缓存尚未被持久化到存储层,因此无法复用第一次请求的结果。加上API返回随机内容,所以两次请求得到不同的笑话。
2. 静态页面刷新后数据变化的原因
点击调用router.refresh()的按钮时,会触发Next.js的**增量静态再生(ISR)**机制:
- 该操作会向服务器发起请求,重新执行页面组件的数据获取逻辑(即再次调用
getRandomJoke),从API获取新的随机笑话。 - 服务器会基于新的数据生成更新后的静态页面,并将其缓存。后续访问该页面时,会展示最新的内容,直到下一次触发再生操作。
内容的提问来源于stack exchange,提问作者utg.tdawg
相关产品推荐
相关产品推荐

