Next.js 数据缓存机制---fetch、unstable_cache、use cache指令、React中的cache函数

276 阅读3分钟

Next.js的缓存机制概览

  • 扩展的 fetch API:Next.js 扩展了标准的 Web fetch API,允许通过参数控制缓存行为

  • unstable_cache 函数:专为缓存数据获取函数设计的高阶函数

  • use cache 指令:实验性的指令式缓存方案,未来可能替代 unstable_cache

  • React 的 cache 函数:React 服务器组件提供的请求级缓存机制

扩展的fetch API(推荐使用)

Next.js拓展web标准的fetch API,持久化缓存能力。

基本语法

fetch(url,{
  cache:'force-cache' | 'no-store',
  next:{
    revalidate:number | false,
    tags:['tag1','tag2']
  }
})

缓存策略选项

  1. cache 选项

    • 'auto no cache'(默认):在开发环境中每次请求都从服务器获取,在构建时只获取一次。如果检测到路由使用了动态 API,则每次请求都会从服务器获取
    • 'force-cache':优先从缓存获取,缓存不存在或过期时从服务器获取
    • 'no-store':每次请求都从服务器获取新数据,即使路由没有使用动态 API
  2. next.revalidate 选项

    • 设置缓存生命周期(秒)
    • false:无限期缓存
    • 0:禁止缓存
    • number:指定缓存时间(秒)
  3. next.tags 选项

    • 为缓存资源添加标签
    • 可通过 revalidateTag API 按需重新验证

示例:

// 默认行为 - 开发环境每次请求获取新数据,生产环境在构建时获取
const response = await fetch('https://api.example.com/data');

// 强制使用缓存
const cachedData = await fetch('https://api.example.com/data', { 
  cache: 'force-cache' 
});

// 禁用缓存,每次请求都获取新数据
const freshData = await fetch('https://api.example.com/data', { 
  cache: 'no-store' 
});

// 设置缓存时间为1小时
const revalidatedData = await fetch('https://api.example.com/data', { 
  next: { revalidate: 3600 } 
});

// 使用缓存标签,方便按需重新验证
const taggedData = await fetch('https://api.example.com/data', { 
  next: { tags: ['product-data'] } 
});

适用场景

  • 简单的HTTP请求:只需要获取和缓存外部API数据时
  • 需要精细控制缓存行为:设置具体的缓存时间或使用缓存标签时
  • 需要稳定性:稳定、不变的API时

unstable_cache函数

unstable_cache是Next.js的一个高阶函数,用于包装和缓存任意异步函数的结果,适合数据获取函数。

》基本语法

import { unstable_cache } from 'next/cache';

const getCachedData = unstable_cache(
  async (...args) => {
    // 异步数据获取或计算逻辑
    return result;
  },
  ['cache-key-prefix'],
  { revalidate: 60, tags: ['data-tag'] }
);

参数说明

  1. 第一个参数:要缓存的异步函数

  2. 第二个参数:缓存键前缀数组

  3. 第三个参数:缓存配置选项

    • revalidate:缓存时间(秒)
    • tags:缓存标签,用于按需重新验证

示例

import { unstable_cache } from 'next/cache';

// 基本用法
const getUser = unstable_cache(
  async (userId) => {
    const res = await fetch(`https://api.example.com/users/${userId}`);
    return res.json();
  },
  ['user-data'],
  { revalidate: 3600, tags: ['user'] }
);

// 在组件中使用
export default async function UserProfile({ userId }) {
  const user = await getUser(userId);
  return <div>{user.name}</div>;
}

适用场景

  • 需要缓存多个请求的组合结果:需要获取多个数据源并组合使用时
  • 需要缓存复杂计算:
  • 需要精细控制缓存键:

use cache 指令

use cache 是 Next.js 的一个实验性指令,用于缓存函数、组件或路由的输出。它使用了类似 'use client' 的指令式语法。

基本语法

async function getData() {
  'use cache'
  // 数据获取或计算逻辑
  return result;
}

配置选项

虽然 use cache 本身不接受参数,但可以与 Next.js 的其他 API 配合使用:

  • cacheLife API 控制缓存生命周期
  • cacheTag API 添加缓存标签

示例

// 基本用法
export async function getUser(userId) {
  'use cache'
  const res = await fetch(`https://api.example.com/users/${userId}`);
  return res.json();
}

// 在组件中使用
export default async function UserProfile({ userId }) {
  const user = await getUser(userId);
  return <div>{user.name}</div>;
}

适用场景:

  • 需要缓存整个组件或路由
  • 简洁语法

React的cache函数

React 服务器组件提供了 cache 函数,用于在单个请求的生命周期内缓存函数结果。

基本语法

import { cache } from 'react';

const getData = cache(async (...args) => {
  // 数据获取或计算逻辑
  return result;
});

示例

import { cache } from 'react';

// 缓存数据获取函数
const getUser = cache(async (userId) => {
  const res = await fetch(`https://api.example.com/users/${userId}`);
  return res.json();
});

// 在多个组件中使用
function UserProfile({ userId }) {
  const user = getUser(userId);
  return <div>{user.name}</div>;
}

function UserStats({ userId }) {
  const user = getUser(userId);  // 相同参数调用会复用缓存结果
  return <div>Posts: {user.posts.length}</div>;
}

适用场景

  • 单个请求内共享数据
  • 避免重复计算
  • 无需跨请求持久化

四种缓存机制对比

截屏2025-04-01 13.43.30.png