实用的 Next.js 缓存:路由、数据、重新验证和标签

发布: (2026年1月1日 GMT+8 14:26)
10 min read
原文: Dev.to

I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content of the article (excluding the source line you’ve already provided) here? Once I have the text, I’ll translate it into Simplified Chinese while preserving the original formatting, markdown, and technical terms.

快速概览

  • 了解 路由(HTML)缓存与数据(API)缓存的区别以及何时优先使用它们。
  • 学习 基于时间、事件驱动和标签的重新验证模式。
  • 查看 常见的反模式以及生产就绪检查清单。
  • 获取 调试技巧和用于验证缓存行为的运维命令。

为什么缓存对 Next.js 很重要

Next.js 应用混合了服务器渲染、边缘运行时和客户端获取。
缓存将这些部分串联起来,能够:

  • 提升感知速度。
  • 减轻源站负载。
  • 降低基础设施成本。

恰当组合 路由缓存数据缓存重新验证 策略,就能高效地提供新鲜内容。

事实: 服务器端缓存 + 正确的重新验证,在安全且有意的实现下,可降低首字节时间(TTFB)和源站成本。

常见缓存层

层级缓存内容适用场景控制机制
路由缓存HTML 响应(页面)完整页面加速、低计算消耗getStaticProps + revalidate、ISR、按需重新验证
数据缓存JSON / API 响应跨页面共享数据fetch 缓存模式、边缘缓存头部
标签失效一组页面 / 数据更新后进行选择性失效标签、基于标签的重新验证端点
浏览器缓存客户端资源减少重复网络请求Cache‑Control 头部

快速概念映射

  • 路由缓存 = 快速的完整页面交付(SSG,ISR)。
  • 数据缓存 = 在路由/组件之间共享的 JSON 或 API 响应。
  • 标签 = 对被多个页面引用的实体进行细粒度失效。

路由缓存模式

  1. 基于时间的 ISR – 定期再生成。
  2. 按需重新验证 – 内容更改时触发刷新。
  3. 标签驱动的重新验证 – 仅刷新依赖于已更改实体的页面。

示例:getStaticProps + revalidate

// pages/products/[id].js
export async function getStaticProps({ params }) {
  const product = await fetchProduct(params.id);
  return {
    props: { product },
    revalidate: 60, // seconds
  };
}

revalidate: 60 告诉 Next.js 每 60 秒在后台刷新页面,同时提供缓存的 HTML。

示例:使用 fetch 的数据缓存

export async function getServerSideProps({ params }) {
  const res = await fetch(`${API}/products/${params.id}`, {
    cache: 'force-cache', // or default for long‑lived results
  });
  const product = await res.json();
  return { props: { product } };
}

指南

Cache Mode使用场景
no-store始终返回最新响应(更高的源站成本)。
force-cache / default长期有效的结果(在请求之间共享)。
Custom TTLs在新鲜度与成本之间取得平衡。

重新验证策略

策略描述典型用例
基于时间 (ISR)可预测的周期性刷新。营销页面、博客索引。
事件驱动(按需)通过 webhook 或管理员操作触发。产品更新、内容发布。
标签驱动为页面/数据附加标签;仅重新验证这些标签的页面。被多个页面引用的实体(作者、分类)。

按需重新验证端点

// pages/api/revalidate.ts
export default async function handler(req, res) {
  const { secret, path } = req.body;

  if (secret !== process.env.MY_SECRET) {
    return res.status(401).end();
  }

  await res.revalidate(path);
  return res.json({ revalidated: true });
}

使用密钥令牌来保护此端点。

基于标签的失效(概念)

  1. 渲染期间 – 附加标签(例如 product:123author:alice)。
  2. 数据变更时 – 调用标签重新验证 API,以刷新所有包含这些标签的页面。

提示: 当多个页面引用同一实体时,标签的优势显现;它们可以避免强行全站重建。

实用检查清单

  • 根据内容波动性选择 routedata 缓存。
  • 设置合理的 revalidate 间隔;避免对中等变化的内容使用极高的值。
  • 使用密钥验证实现 on‑demand 端点。
  • 对共享实体(产品、作者、分类)使用 tags
  • 在所有层记录 TTL,以防冲突。
  • 在生产部署前,本地禁用缓存进行验证。

调试与验证

  • 检查响应头Cache-ControlAgeX-Nextjs-*),使用:

    curl -I https://your-site.com/page
  • 查看 CDN / 源站日志,了解命中‑未命中模式。

  • 如果按需重新验证失败,请确认:

    • 密钥令牌是否正确。
    • 完整的路由路径(包括结尾的斜杠)。

反模式需避免

反模式为什么不好
长 TTL 且没有任何失效路径实际更新后仍然保留陈旧数据。
变更进行全局重新验证浪费计算资源,减慢部署。
系统之间的 TTL 冲突且未文档化新鲜度不可预测。
对中等变化的内容使用非常高的 revalidate且没有可靠的失效触发器内容会变得过时。

警告: 除非拥有可靠的失效机制,否则避免使用高 revalidate 值。

实际场景

1️⃣ 电商产品更新

  • 问题: 每次库存变动后进行全局重新验证导致构建峰值。
  • 解决方案: 按 ID 为产品页面打标签,仅重新验证受影响的标签 → 大幅减少构建次数并提升购物者性能。

2️⃣ 编辑出版

  • 问题: 较长的 ISR 间隔导致标题陈旧。
  • 解决方案: 缩短首页的 revalidate 窗口,并在发布时调用按需重新验证。

3️⃣ 内部仪表盘

  • 问题: 过于激进的缓存导致分析数据陈旧。
  • 解决方案: 对实时小部件使用 cache: 'no-store',同时对非关键卡片保持缓存。

新兴趋势

  • 边缘运行时和细粒度的边缘缓存控制正在成熟。
  • 声明式标签和部分重新验证在框架中变得越来越常见。
  • 对缓存命中/未命中指标的可观测性正在被采纳。

在设计、实现和维护 Next.js 应用程序中的缓存时,请随时参考本指南。

SG vs SSR vs 每页仅客户端

✅ Action Items

  • 为每种内容类型定义重新验证策略(TTL、标签、触发器)。
  • 为共享实体添加基于标签的失效。
  • 实现安全的按需重新验证端点。
  • 为缓存行为监控头信息、CDN 日志和警报。
  • 为团队编写缓存策略文档。

🔧 检查命令

# Inspect response headers
curl -I https://your-site.com/your-path
  • 查看 CDN 日志以获取源请求。
  • 检查服务器日志中的按需重新验证失败。

📌 关键要点

  1. Route cache (SSG/ISR) → 最适合提升整页性能。
  2. Data cache → 适用于共享的 API 响应。
  3. Tag‑based invalidation → 在大型站点上优于全局失效。
  4. Hybrid revalidation → 将基于时间的(TTL)和事件驱动的触发相结合,以实现可预测的刷新。
  5. 避免反模式
    • 长 TTL 且没有任何失效机制。
    • 对小幅编辑使用全局重新验证。
  6. Instrumentation → 使用响应头、CDN 日志和告警来发现缓存未命中热点和异常行为。

一个可持续的 Next.js 缓存策略需要在 速度、最新性和成本 之间取得平衡。根据内容的波动性和规模,混合使用路由缓存、数据缓存和基于标签的失效。持续监控缓存行为,记录决策,并在可能的情况下实现自动重新验证。

📞 想要缓存审查或审计吗?

联系以讨论模式和实现细节。

  • 主页:
  • 博客:
  • 规范:
Back to Blog

相关文章

阅读更多 »

修复 Next.js 中的水合错误

Hydration 错误的常见原因 浏览器/环境问题 - 浏览器扩展注入属性、密码管理器、广告拦截器、辅助功能工具 - Br...