增量静态生成如何避免首屏重复请求?
我在用 Next.js 做一个博客,开启了 ISR(增量静态生成),但发现首屏加载时还是会发起一次 API 请求,明明页面已经预渲染了 HTML。这不就白做了吗?
我试过在 getStaticProps 里返回数据,也确认生成了静态 HTML 文件,但客户端 hydration 阶段还是会重新 fetch 数据。比如下面这段:
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return { props: { posts }, revalidate: 60 };
}
难道 ISR 只能减少构建时间,不能真正避免首屏请求?有没有办法让首屏完全静态、不发任何请求?
但真能解决,而且不复杂。关键点在于:让客户端 hydration 时知道「数据已经就绪」,别再发请求。
核心思路是用
initialProps把服务端拉好的数据注入到页面组件里,然后在getStaticProps里返回revalidate字段的同时,确保数据结构能被useSWR或你自己的 fetch 逻辑识别为「已缓存」。不过最直接的解法是:别自己再在客户端 fetch 一遍。如果你页面数据完全来自
getStaticProps,那组件里就别写useSWR或fetch了,直接用传进来的props.posts。但你可能有这种需求:页面初始静态渲染,后续还能自动 revalidate(比如评论数实时更新)。这时候可以这样搞:
getStaticProps里返回数据,同时加个标记字段,比如isStatic: true;客户端用
useSWR时传个initialData,让它优先用这个数据做 hydration,只在 revalidate 时才真正发请求。示例代码:
或者更偷懒点,如果你用的是
next/link和next/router,可以配合useSWRImmutable(需要自己封装个 hook)或者直接用SWRConfig包一层,给静态页加个fallback。另外提醒一句:别用
getServerSideProps做 ISR,那个是纯 SSR,每次请求都跑,白搭。真要完全零请求,那就别在客户端动任何数据逻辑,纯静态页。但一般博客还是需要点动态更新的,所以用
initialData是最稳的方案。我司现在博客站就这么干的,首屏 0 网络请求,FID 很稳。