[Next.js篇] Next14的缓存有哪些

4 分钟
39 阅读

Next.js 14 的缓存机制通过多层架构优化性能,涵盖客户端服务端及 CDN,开发者可通过灵活配置实现高效数据与页面缓存。以下是详细解析及设置方法:


一缓存层次结构

Next.js 的缓存分为四层,各层协同工作以最大化性能:

  1. 浏览器缓存:通过 Cache-ControlETag 等 HTTP 头控制静态资源和 API 请求的本地存储。
  2. CDN 缓存:利用 CDN 节点缓存静态资源和 ISR(增量静态再生)生成的页面,加速全球访问。
  3. 服务端缓存
    • 请求记忆化(Request Memoization):自动缓存同一请求的响应,避免重复调用 fetch
    • 数据缓存(Data Cache):持久化存储 API 响应数据,支持跨请求复用。
  4. 全路由缓存(Full Route Cache):缓存整个页面的 HTML 和 RSC(React Server Component)负载,减少渲染成本。
  5. 客户端路由缓存(Router Cache):在客户端缓存导航时的 RSC 数据,提升路由切换速度。

二、核心缓存机制与配置方法

1. 请求记忆化(Request Memoization)

Next.js 扩展了 fetch API,自动缓存相同 URL 和参数的请求,避免重复网络调用:

tsx 复制代码
// 示例:同一请求仅执行一次
async function fetchData() {
  const res = await fetch('https://api.example.com/data');
  return res.json();
}

const data1 = await fetchData(); // 首次请求
const data2 = await fetchData(); // 从缓存读取,无网络请求

适用场景:组件树中多处调用相同数据时,无需手动传递 props。


2. 数据缓存(Data Cache)

通过 cache 函数或 API 路由手动控制数据缓存:

  • 使用 cache 函数

    tsx 复制代码
    import { cache } from 'react';
    
    export const getCachedData = cache(async () => {
      const res = await fetch('https://api.example.com/data');
      return res.json();
    });

    该函数在请求生命周期内缓存结果,适合服务端组件复用数据。

  • API 路由设置 Cache-Control

    ts 复制代码
    // app/api/example/route.ts
    export async function GET() {
      const data = await getCachedData();
      return Response.json(data, {
        headers: {
          'Cache-Control': 'public, max-age=3600, s-maxage=600', // 浏览器缓存1小时,CDN缓存10分钟
        },
      });
    }

    通过设置 s-maxage 控制 CDN 缓存时长,max-age 控制浏览器缓存。


3. 全路由缓存(Full Route Cache)与 ISR

  • 静态生成(SSG)
    使用 export const revalidate = 3600; 启用 ISR,页面在构建后每隔指定时间重新生成:

    tsx 复制代码
    // app/page.tsx
    export const revalidate = 3600; // 每小时重新生成页面
    
    export default async function Page() {
      const data = await fetch('https://api.example.com/data');
      return <div>{data}</div>;
    }

    页面首次访问时生成,后续请求返回缓存内容,直到过期。

  • 动态路由缓存
    动态路由需显式声明 dynamic = 'force-dynamic',但需注意 Next.js 14.2.12 后动态路由默认不添加 Cache-Control 头,需手动设置:

    tsx 复制代码
    // app/dynamic/[id]/page.tsx
    export const dynamic = 'force-dynamic';
    
    export default function DynamicPage() {
      return (
        <div>
          <h1>Dynamic Content</h1>
        </div>
      );
    }

4. 客户端路由缓存(Router Cache)

Next.js 在客户端缓存导航时的 RSC 数据,默认保留当前会话或一段时间。若需强制刷新,可调用 router.refresh()


三高级缓存策略

1. Stale-While-Revalidate(SWR)

通过 swrDelta 配置旧数据可用时长,允许在后台重新验证数据:

js 复制代码
// next.config.js
module.exports = {
  experimental: {
    swrDelta: 31536000, // 1年,旧数据可立即返回,后台更新
  },
};

结合 max-agerevalidate)与 stale-while-revalidate,实现类似 HTTP 头的缓存策略:

http 复制代码
Cache-Control: max-age=3600, stale-while-revalidate=30

适用于频繁访问但更新不频繁的内容(如博客)。

2. 按标签重新验证(Revalidate by Tag)

通过 revalidateTag 实现细粒度缓存失效:

ts 复制代码
// 刷新特定标签的数据
await revalidateTag('products');

// API 路由中绑定标签
export async function GET() {
  const data = await fetch('https://api.example.com/data', { next: { tags: ['products'] } });
  return Response.json(data);
}

此方法常用于 CMS 更新后即时刷新关联页面。


四最佳实践与注意事项

  1. 缓存优先级

    • 浏览器缓存 > CDN 缓存 > 服务端缓存。
    • 动态内容(如用户登录状态)应设置 Cache-Control: no-cache,避免 CDN 缓存。
  2. 缓存失效策略

    • 使用 revalidateTagrevalidatePath 主动清除缓存,而非依赖过期时间。
    • 对数据库更新操作,建议结合 cache 函数的 revalidate 参数。
  3. 动态路由的缓存控制
    Next.js 14.2.12+ 动态路由默认无 Cache-Control 头,需手动设置以避免 CDN 错误缓存。

  4. 第三方库集成

    • 客户端数据同步可结合 SWR 或 React Query,通过 initialData 复用服务端数据。
    • CDN 缓存需配合 s-maxagestale-while-revalidate 实现高性能。

服务器端方式(searchParams):适用于需要动态加载数据的场景,但会有延迟。
客户端方式(useSearchParams):适用于即时更新的场景,比如更改颜色、排序等简单操作。

总结

Next.js 14 的缓存机制覆盖全栈,开发者可通过 fetch 自动缓存cache 函数、ISRHTTP 头及标签重验证等手段,灵活控制缓存行为。合理配置不仅能提升性能,还能降低服务器负载,但需注意动态内容的缓存失效策略。

评论

评论

发表评论