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

Next.js 12.3中如何仅缓存getServerSideProps页面并避开app.tsx?

解决Next.js中仅缓存页面内容而避开app.tsx的方案

核心思路

要实现仅缓存公共数据页面、避开app.tsx中的用户动态数据,关键是分离服务端渲染的公共内容与客户端处理的用户私有内容,同时精准控制缓存策略。

方法1:用增量静态再生(ISR)替代getServerSideProps

如果页面数据对所有访问者一致,直接用ISR生成可缓存的静态页面,完全避免getServerSideProps的每次请求渲染。app.tsx中的用户数据仅在客户端处理,不会被混入缓存页面。

// 目标页面(如 pages/public-data-page.tsx)
export async function getStaticProps() {
  // 获取所有用户共享的后端公共数据
  const publicDataRes = await fetch('https://your-api.com/public-data');
  const publicData = await publicDataRes.json();

  return {
    props: { publicData },
    revalidate: 300, // 每5分钟自动重新生成页面(可根据需求调整)
  };
}

export default function PublicDataPage({ publicData }) {
  return <div>{/* 渲染公共数据 */}</div>;
}

同时修改app.tsx,将用户认证状态等动态逻辑移到客户端:

// app.tsx
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { setUserAuth } from '@/redux/slices/authSlice';

export default function App({ Component, pageProps }) {
  const dispatch = useDispatch();

  useEffect(() => {
    // 仅在客户端加载用户认证数据
    const loadUserAuth = async () => {
      const res = await fetch('/api/auth/current-user');
      const authData = await res.json();
      dispatch(setUserAuth(authData));
    };
    loadUserAuth();
  }, [dispatch]);

  return <Component {...pageProps} />;
}

方法2:精准控制缓存头(适用于仍需使用getServerSideProps的场景)

如果必须保留getServerSideProps,可在页面的getServerSideProps中设置缓存头,同时确保app.tsx不传递任何用户动态数据到服务端渲染的HTML中。

// 目标页面的getServerSideProps
export async function getServerSideProps(context) {
  const publicDataRes = await fetch('https://your-api.com/public-data');
  const publicData = await publicDataRes.json();

  // 设置页面缓存策略
  context.res.setHeader(
    'Cache-Control',
    's-maxage=600, stale-while-revalidate=300' // 缓存10分钟,过期后仍可返回旧内容同时更新
  );

  return {
    props: { publicData },
  };
}

注意:app.tsx中绝对不要在服务端渲染阶段注入用户数据(比如通过getInitialProps或服务端props传递),所有用户相关逻辑必须放在useEffect或客户端初始化钩子中。

方法3:用Edge Middleware区分缓存规则

通过Middleware针对不同路径设置缓存策略,让公共页面走缓存,app.tsx对应的全局请求强制不缓存。

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const response = NextResponse.next();

  // 对公共页面路径设置缓存
  if (request.nextUrl.pathname.match(/^\/public-.+/)) {
    response.headers.set('Cache-Control', 's-maxage=600, stale-while-revalidate=300');
  } else {
    // 其他路径(含app.tsx相关的全局内容)禁用缓存
    response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate');
  }

  return response;
}

// 指定Middleware生效的路径
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

关键注意事项

  • 绝对不要将用户认证状态、私有数据等动态内容混入服务端渲染的页面props中,否则会被一起缓存。
  • 确保app.tsx的服务端渲染输出仅包含静态框架,所有动态用户逻辑完全在客户端执行。

内容的提问来源于stack exchange,提问作者Hkm Sadek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 12:09:55