解决 Next.js 部署后 API 缓存不刷新的问题

349 阅读2分钟

问题背景

本地开发中,直接访问 /api/chatsessions 能实时获取 PostgreSQL 的最新数据。但部署至服务器跑 PM2、Nginx 反代后,却始终返回旧内容,数据库更新后网页依旧不刷新。


排查步骤

1. 确认 Route Handler 类型

/api/chatsessions 是 App Router 的 Route Handlerroute.ts),默认是动态的,但仍可能使用 数据缓存(Data Cache) ,导致返回旧数据 MediumMedium+11nextjs.org+11Stack Overflow+11


2. dynamic = 'force-dynamic' 不足以清缓存

虽然在 Handler 顶部写了 export const dynamic = 'force-dynamic',它只关闭“完整路由缓存”(Full Route Cache),但不影响数据缓存 nextjs.org+4Reddit+4Stack Overflow+4


3. 缺少 fetchCache = 'force-no-store'

官方说明:需同时添加 export const fetchCache = 'force-no-store'default-no-store,才能跳过 Data Cache,确保每次请求都刷新数据 nextjs.org+1Medium+1


4. 注意斜杠跳转问题

访问 /api/chatsessions 会自动 308 跳转到 /api/chatsessions/。若前端和 Nginx 路径不一致,可能导致缓存配置失效。


解决方案

// app/api/chatsessions/route.ts
export const dynamic = 'force-dynamic';
export const fetchCache = 'force-no-store';

import { NextResponse } from "next/server";
import { Pool } from "pg";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export async function GET() {
  const client = await pool.connect();
  try {
    const { rows } = await client.query(`
      SELECT id, created_at
        FROM chats
       ORDER BY created_at DESC
       LIMIT 50
    `);
    const sessions = rows.map(r => ({ id: r.id, createdAt: r.created_at }));
    return NextResponse.json(sessions, {
      headers: {
        'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'
      }
    });
  } finally {
    client.release();
  }
}
  • dynamic = 'force-dynamic':禁用完整路由缓存
  • fetchCache = 'force-no-store':禁用数据缓存,即 Data Cache
  • 在返回头中加入 Cache-Control: no-store:防止浏览器或代理缓存

辅助配置:Nginx 与前端请求

Nginx 配置

location ^~ /api/ {
  proxy_pass         http://127.0.0.1:3000;
  proxy_cache        off;
  proxy_buffering    off;
  add_header Cache-Control "no-store, max-age=0" always;
}

前端 fetch 示例

await fetch('/api/chatsessions/', { cache: 'no-store' });

确保 API 路径统一带斜杠,避免 308 重定向带来的缓存问题。


验证方法

  1. 修改数据库内容后,使用 curl -i https://.../api/chatsessions/ 查看响应头是否带 Cache-Control: no-store
  2. 访问接口并刷新页面,应立即获取最新数据。

总结

  • Next.js Route Handler 默认仍使用数据缓存,需要配合使用 dynamic + fetchCache 才能彻底关闭;
  • 保证 API 路径带斜杠,防止跳转时走代理缓存;
  • 全链路禁缓存保障(路由层 + Handler + Nginx + 前端),即可实现“每次请求都实时更新”。

这篇记录了从问题定位到解决完整流程,希望能帮助遇到同样问题的同学。