Nextjs支持的哪些缓存

·1800·4 分钟·
AI摘要: 本文详细介绍了Next.js在不同层面支持的缓存机制,包括API层面的响应头控制、Fetch函数的缓存策略、Cache函数实现的函数级缓存、页面级别的ISR缓存以及跨实例的KV分布式缓存。重点解析了各层级的技术实现方式和适用场景,如通过Cache-Control头部设置浏览器/CDN缓存时效性、force-cache强制边缘缓存特性、react.cache高阶函数优化重复计算逻辑等关键技术点。

在Vercel中,nextjs为了支持severless特性,支持了各种层面的缓存能力。

API层面

Nextjs支持通过在/app/api目录下,通过route.ts对外开放一个api接口,那么接口级别的缓存方式为:


export async function GET() {

    xxx

    return NextResponse.json(

      { categories: formattedCategories },

      {

        status: 200,

        headers: {

          "Cache-Control": "public, max-age=60, stale-while-revalidate=30"

        }

      }

    );

}

  • max-age=60: 通常设置为60s,表示浏览器/Edge Cache缓存60s

  • stale-while-revalidate=30:国企之后,继续返回旧数据,同时后台异步更新

  • 缓存可以在Edge/CDN层生效,减少数据库压力

Fetch函数缓存

Nextjs中经常使用Fetch来从其他接口(内部或者外部)来获取数据,也可以进行缓存:


export async function GET() {

  const res = await fetch("https://api.example.com/data", { cache: "force-cache" });

  const data = await res.json();

  return NextResponse.json(data);

}



  • cache的取值:[“no-store”, “force-cache”, “default”]

  • 主要作用在内部Fetch,而不是控制最终HTTP响应,配合revalidate可以实现ISR

Cache缓存

Nextjs还提供了Cache函数,支持对函数级别缓存,避免重复执行函数逻辑


import { cache } from "react";



const getCategories = cache(async function () {

  console.log("fetching categories");

  const categories = await prisma.resource.groupBy({

    by: ["category"],

    _count: { id: true },

  });

  return categories;

});



export async function GET() {

  const categories = await getCategories();

  return NextResponse.json({ categories });

}



  • 缓存范围为同一个server实例内部重复调用,直接返回缓存结果,不再重复执行函数体

  • Serverless实例冷启动之后,缓存会丢失

  • 比较适用一些频繁调用的函数(如查询数据库,计算密集型逻辑)

页面级别缓存

还有一个更顶层一点的页面级别缓存,一般用于ISR,通过export const revalidate = xxx;实现

不过export const revalidate = xxx似乎不支持计算表达式,必须计算出具体的重新验证的时间数值,比较不智能

KV缓存

之前所有的都是同一个Serverless实例内部缓存,如果跨实例,那么需要一个类似redis的分布式缓存中间件,比如Vercel KV