You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

客户端已有未过期缓存时,如何在NextJS中跳过SSR

在Next.js + TanStack Query中实现缓存新鲜时跳过SSR

核心思路

借助TanStack Query的缓存状态判断数据是否新鲜,结合Next.js客户端导航特性,实现首次访问用SSR渲染、缓存未过期时直接复用客户端缓存跳过重复请求的效果。

具体实现

1. 封装自定义CachedLink组件

Next.js原生<Link>没有skipSsr属性,自己封装一个组件来实现缓存判断逻辑:

import Link from 'next/link';
import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';

type CachedLinkProps = {
  href: string;
  todoId: string;
  children: React.ReactNode;
};

export default function CachedLink({ href, todoId, children }: CachedLinkProps) {
  const queryClient = useQueryClient();
  const router = useRouter();
  
  // 检查对应todo的缓存是否存在且未过期
  const isCacheFresh = queryClient.getQueryData(['todo', todoId]) && 
    !queryClient.isQueryStale(['todo', todoId]);

  return (
    <Link 
      href={href}
      // 缓存新鲜时关闭预取,避免不必要的请求
      prefetch={!isCacheFresh}
      onClick={(e) => {
        if (isCacheFresh) {
          e.preventDefault();
          // 手动跳转到目标路由,触发客户端渲染
          router.push(href);
        }
      }}
    >
      {children}
    </Link>
  );
}

2. 调整详情页的数据获取逻辑

保留SSR初始化逻辑的同时,让组件优先复用客户端缓存:

import { useQuery } from '@tanstack/react-query';
import { GetServerSideProps } from 'next';

export default function TodoDetail({ initialTodo }) {
  // useQuery会优先用initialTodo或客户端缓存,缓存过期才重新请求
  const { data: todo } = useQuery({
    queryKey: ['todo', initialTodo.id],
    queryFn: () => fetch(`/api/todos/${initialTodo.id}`).then(res => res.json()),
    initialData: initialTodo,
  });

  return (
    <div>
      <h1>{todo.title}</h1>
      <p>{todo.description}</p>
    </div>
  );
}

// 首次访问/缓存过期时,通过SSR获取初始数据
export const getServerSideProps: GetServerSideProps = async (context) => {
  const { id } = context.params as { id: string };
  const res = await fetch(`https://your-backend-api.com/todos/${id}`);
  const initialTodo = await res.json();

  return { props: { initialTodo } };
};

3. 关键配置与说明

  • 缓存新鲜度判断:queryClient.isQueryStale(['todo', todoId])返回false时,说明缓存未过期,可跳过SSR
  • 全局缓存时长:可以在TanStack Query初始化时设置默认staleTime,统一控制缓存新鲜周期:
import { QueryClient } from '@tanstack/react-query';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000, // 5分钟内缓存视为新鲜,可按需调整
    },
  },
});
  • 路由跳转逻辑:缓存新鲜时手动调用router.push,触发Next.js的客户端路由更新,直接复用缓存数据渲染页面,不会触发getServerSideProps

内容的提问来源于stack exchange,提问作者Daniel Reina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 23:06:09