如何退出Next.js v13路由缓存?设置响应头仍缓存的问题
问题:Next.js API路由设置
no-store仍被缓存,x-nextjs-cache:HIT与cache-control共存是否违反规范? 我编写了如下route.ts代码:
import { NextResponse } from 'next/server'; import { serializeError } from 'serialize-error'; export const GET = async () => { try { // ... } catch (error) { return NextResponse.json({ error: serializeError(error), }, { status: 500, }); } const response = NextResponse.json({ status: 'OK', }); response.headers.set('cache-control', 'no-store'); response.headers.set('x-robots-tag', 'noindex'); return response; };
无论我在响应中添加什么头信息,响应始终被缓存。以下是curl请求示例:
curl -v https://... * Trying 104.196.232.237:443... * Connected to ray.run (104.196.232.237) port 443 (#0) * ALPN: offers h2 * ALPN: offers http/1.1 * CAfile: /etc/ssl/cert.pem * CApath: none * (304) (OUT), TLS handshake, Client hello (1): * (304) (IN), TLS handshake, Server hello (2): * (304) (IN), TLS handshake, Unknown (8): * (304) (IN), TLS handshake, Certificate (11): * (304) (IN), TLS handshake, CERT verify (15): * (304) (IN), TLS handshake, Finished (20): * (304) (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 * ALPN: server accepted h2 * Server certificate: * subject: CN=ray.run * start date: May 27 01:05:38 2023 GMT * expire date: Aug 25 01:05:37 2023 GMT * subjectAltName: host "ray.run" matched cert's "ray.run" * issuer: C=US; O=Let's Encrypt; CN=R3 * SSL certificate verify ok. * Using HTTP2, server supports multiplexing * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * h2h3 [:method: GET] * h2h3 [:path: ...] * h2h3 [:scheme: https] * h2h3 [:authority: ray.run] * h2h3 [user-agent: curl/7.86.0] * h2h3 [accept: */*] * Using Stream ID: 1 (easy handle 0x11e811400) > GET /... HTTP/2 > Host: ray.run > user-agent: curl/7.86.0 > accept: */* > < HTTP/2 200 < x-dns-prefetch-control: on < x-frame-options: DENY < x-content-type-options: nosniff < x-xss-protection: 1; mode=block < referrer-policy: origin-when-cross-origin < permissions-policy: camera=(), microphone=(), geolocation=(), interest-cohort=() < strict-transport-security: max-age=63072000; includeSubDomains; preload < vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding < x-nextjs-cache: HIT < cache-control: no-store < content-type: application/json < x-robots-tag: noindex < date: Fri, 16 Jun 2023 00:56:58 GMT < server: railway < * Connection #0 to host ray.run left intact
响应中同时出现x-nextjs-cache: HIT和cache-control: no-store,这是否说明Next.js公然无视规范?
解答
这不是Next.js无视HTTP规范,而是要区分Next.js内部缓存机制和HTTP缓存头的不同作用:
x-nextjs-cache: HIT是Next.js App Router的内部缓存标识,仅代表它从自身的静态缓存池返回了响应,和HTTP规范没有冲突。cache-control: no-store是正确返回给下游(客户端、CDN等)的HTTP头,作用是禁止这些环节缓存响应,Next.js并没有忽略这个规范——你可以看到响应里确实正确输出了该头。
要解决Next.js内部缓存的问题,你需要显式禁用该API路由的静态优化,因为App Router的API路由默认是静态渲染并缓存的。只需在route.ts顶部添加以下任意一行配置:
// 强制路由为动态,每次请求都重新执行逻辑 export const dynamic = 'force-dynamic';
或者:
// 设置缓存过期时间为0,禁用静态缓存 export const revalidate = 0;
添加后,Next.js会每次请求都重新运行API逻辑,x-nextjs-cache会变为MISS,同时cache-control: no-store依然会正常作用于下游。
另外,也可以直接在创建响应时指定头信息,写法更简洁:
const response = NextResponse.json( { status: 'OK' }, { headers: { 'cache-control': 'no-store', 'x-robots-tag': 'noindex' } } );
内容的提问来源于stack exchange,提问作者Luc Gagan
相关产品推荐
相关产品推荐

