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

Next.js 14.2.8生产环境API缓存异常:掷骰子接口重复请求无更新

生产环境下Next.js掷骰子API请求被缓存,无法更新数据

开发模式下掷骰子API运行正常,但生产构建后,首次请求的数据会被缓存,再次调用API时页面数据无法更新。


掷骰子API代码

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  const diceRollCalc = (min: number, max: number): number => {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1) + min);
  };

  const result = diceRollCalc(1, 6);

  const response = NextResponse.json(result);
  response.headers.set('Cache-Control', 'no-cache, no-store, must-revalidate');
  return response;
}

调用API的React客户端组件代码

'use client'
import { useEffect, useState } from 'react';

function DiceRoll() {
  const [data, setData] = useState<number | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('/api/diceRoll', {
        cache: 'no-store',
        headers: {
          "Cache-Control": "no-cache, no-store, must-revalidate",
          "Pragma": "no-cache",
          "Expires": "0",
        }
      });
      const result = await response.json();
      setData(result);
    };

    fetchData();
  }, []);

  const handleButtonClick = async () => {
    const response = await fetch('/api/diceRoll');
    const result = await response.json();
    setData(result);
  };

  return (
    <div>
      {data && <p>结果: {data}</p>}
      <button onClick={handleButtonClick}>掷骰子</button>
    </div>
  );
}

export default DiceRoll;

页面组件代码

import React from 'react';
import DiceRoll from './diceRollClient';

export default function DicePage() {
  return (
    <div id='main'>
      <h1>掷骰子</h1>
      <DiceRoll/>
    </div>
  );
}

开发模式与生产模式响应头对比

开发模式

Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
cache-control: no-cache, no-store, must-revalidate
content-type: application/json
vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch

生产模式

Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
cache-control: no-cache, no-store, must-revalidate
content-type: application/json
vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch
x-nextjs-cache: HIT

问题原因与解决方案

问题核心是按钮点击时的fetch请求未设置缓存控制参数,Next.js生产环境默认会缓存GET请求,即使API返回了no-cache响应头,客户端请求如果没有明确禁用缓存,仍会命中Next.js的内置缓存(表现为x-nextjs-cache: HIT)。

解决方法

  1. 修改客户端fetch请求
    在按钮点击的fetch调用中添加缓存禁用配置,和useEffect中的请求保持一致:

    const handleButtonClick = async () => {
      const response = await fetch('/api/diceRoll', { cache: 'no-store' });
      const result = await response.json();
      setData(result);
    };
    

    仅设置cache: 'no-store'即可,该参数会直接告诉Next.js不要缓存此请求。

  2. 在API路由中强制禁用缓存
    在API路由代码顶部添加revalidate: 0配置(Next.js 13+ App Router适用),确保API每次请求都重新执行:

    import { NextResponse } from 'next/server';
    
    export const revalidate = 0; // 强制禁用缓存
    
    export async function GET(request: Request) {
      // ... 原有代码
    }
    

两种方式结合使用,可彻底避免生产环境下的缓存问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:13:15