07 - Understanding & Configuring Caching

07 - Understanding & Configuring Caching
07 - Understanding & Configuring Caching
type
Post
status
Published
date
Dec 24, 2025
slug
nextjs-007
summary
07 - Understanding & Configuring Caching
tags
Next.js
category
编程学习
icon
password
😀
 

001 Module Introduction

  • 回顾前期数据操作知识并引出缓存问题:提及前几节学习的数据获取与修改知识,指出实际应用中可能出现数据不立即更新或页面未按预期更新的情况,原因是 Next.js 会进行数据缓存,进而引出本节对缓存相关内容的探讨。
  • 明确本节缓存学习重点:分析 Next.js 缓存数据和页面的机制及其意义,同时介绍学习者将掌握的技能,包括让 Next.js 重新验证和丢弃缓存数据以显示更新数据,以及根据数据源控制数据缓存范围。

002 Making Sense of NextJS' Caching Types - Next.js 缓存机制

notion image

一、缓存激进程度与版本关联

  1. 版本差异:Next.js 缓存策略的激进程度随版本变化,Next.js 14 提供最激进的缓存;Next.js 15 及更高版本因缓存行为和默认设置调整,缓存激进性有所降低。
  1. 版本查看:可通过检查项目中 package.json 文件,确定当前使用的 Next.js 版本。

二、四大核心缓存类型

缓存类型
管理位置
核心作用
有效期/失效场景
关键特点
请求备忘录(Request Memoization)
服务器端
存储相同配置的数据请求,避免单个请求处理过程中向数据源发送重复请求
仅在单个服务器请求处理周期内有效
针对“单次请求内的重复请求”优化,不长期存储数据
数据缓存(Data Cache)
服务器端
存储从数据源获取的数据,数据未变时重用,减少数据源往返
持续到手动重新验证达到设定时间
长期缓存数据,需主动管理有效期,直接提升数据获取速度
完整路由缓存(Full Route Cache)
服务器端
缓存整个页面(HTML 代码 + React 服务器组件负载),避免页面重新渲染
与关联数据缓存同步,数据更新时页面重新渲染
优化页面加载速度,跳过渲染流程,直接复用完整页面资源
路由器缓存(Router Cache)
客户端(浏览器内存)
存储 React 服务器组件负载,加快页面间导航,减少向服务器的请求
1. 服务器渲染新页面时 2. 用户离开并返回网站时
Next.js 15 中激进性降低,避免数据不一致;支持前后导航快速切换

三、关键补充信息

  1. 文档参考:Next.js 官方文档有专门页面详细解释四种缓存,包含本讲座链接及辅助理解的图形,可进一步深入学习。 Guides: Caching | Next.js
  1. 后续重点:将围绕“服务器端免费缓存”(请求备忘录、数据缓存、完整路由缓存)展开,学习缓存工作原理、数据验证方法及对开发者的实际意义(如避免数据过期、优化性能)。

003 Project Setup

一、核心项目配置与环境搭建

1. 启动项目结构

  • 视频提供的启动项目包含两大模块,分别是 Next.js 应用与独立后端,后续课程会移除独立后端,但该后端可用于深入学习 Next.js 缓存机制。
  • Next.js 应用操作:运行npm install安装所有依赖,再通过npm run dev启动开发服务器。
  • 独立后端操作:先导航到后台文件夹,执行npm install安装依赖,然后用npm start启动后台服务器;此后端为简单 Node Express 应用,仅提供假消息,且带有日志记录功能,能辅助理解 Next.js 缓存对请求的影响。

2. 项目运行要求

  • 需同时启动后端和 Next.js 开发服务器,之后访问localhost:3000,可查看页面并导航到消息板块,以此探索 Next.js 缓存数据及避免请求的时机与方式。

004 Handling Request Memoization

一、核心概念

请求备忘录(Request Memoization)是Next.js内置的性能优化机制,作用是避免向同一数据源发送重复请求,仅发送1次请求后,在应用内所有需要该响应的地方重用数据,减少服务器压力与网络开销。

二、核心生效条件

该机制仅对配置完全相同的请求生效(以fetch函数请求为例),任何配置差异(如请求头、参数、URL等)都会被判定为不同请求,导致重复发送。
  • 反例:视频中在layout.jspage.js向同一后端发送请求时,因设置了不同请求头(用于标记请求来源),后端日志显示2条重复请求。
  • 正例:移除两处请求的自定义请求头,使请求签名完全一致后,刷新页面仅触发1次后端请求。

三、实操关键步骤

  1. 排查重复请求:启动后端服务器,刷新页面后查看后端日志,若出现多次相同数据源的请求,需检查请求配置是否一致。
  1. 统一请求配置:确保同一数据源的请求(如不同组件/页面发起的请求)在请求头、参数、URL等关键配置上完全相同。
  1. 重置缓存(必要时)
      • 若Next.js缓存导致请求结果未更新,可删除项目根目录下的.next文件夹(含临时缓存数据)。
      • 重启Next.js开发服务器与后端服务器,生成新鲜数据并清除旧日志,便于观察优化效果。

四、适用场景扩展

  • 基础场景:避免对独立后端服务的重复fetch请求(视频核心案例)。
  • 扩展场景:可用于优化数据库请求,避免在多个组件中对同一数据库数据发起重复查询(视频预告后续内容)。

005 Understanding The Data Cache & Cache Settings - 数据缓存与 fetch 配置

一、版本差异:fetch 默认缓存行为

Next.js 版本
默认缓存设置
核心表现
验证方式
14 及更早版本
force-cache
1. 初始请求后,刷新页面/导航不会发送新请求<br>2. 后端无新日志生成
观察后端日志,无新增条目
15 及更高版本
no-store
1. 每次刷新/导航都会向后端发送新请求<br>2. 后端持续生成新日志
观察后端日志,多次刷新有新增条目
  • 版本查看:通过项目根目录的 package.json 文件中 next 依赖的版本号确认

二、数据缓存核心原理

  1. 缓存位置:Next.js 内部管理的 服务器端缓存(非浏览器缓存),Next.js 会覆盖 Node.js 内置的 fetch 函数(仅服务器端),用于识别缓存配置并控制缓存行为;
  1. 缓存触发:使用 fetch 函数从后端获取数据时,自动将响应数据存入服务器端缓存
  1. 默认行为:缓存数据会被 永久重用,除非主动告知 Next.js 清除缓存

三、缓存控制核心配置(fetch 扩展参数)

1. 基础缓存策略

配置值
作用
适用场景
force-cache
激进缓存,复用缓存直至主动失效
数据更新频率低(如静态页面、商品基础信息)
no-store
完全不缓存,每次请求都拉取新数据
实时性要求高(如秒杀倒计时、用户实时状态)

2. 缓存过期控制:revalidate

  • 作用:定义缓存数据的有效期(秒),超时后自动丢弃缓存并重新请求;
  • 特点:每次获取新数据后,有效期会重新计时(滚动过期);
  • 适用场景:平衡缓存性能与数据时效性(如商品价格、榜单数据)。

3. 主动触发缓存失效:revalidatePath

  • 作用:手动清除指定路径的缓存,强制重新获取数据;
  • 适用场景:数据更新后(如后台修改商品信息),主动触发页面缓存刷新。

四、示例代码

1. 基础缓存策略(Next.js 14/15 兼容)

2. 带过期时间的缓存(revalidate)

3. 主动触发缓存失效(revalidatePath)

五、关键注意事项

  1. fetch 缓存配置仅在服务器端生效(服务器组件、API 路由),客户端 fetch 遵循浏览器默认缓存规则;
  1. revalidate 优先级高于 cache:即使设置 force-cache,到达 revalidate 时间仍会刷新缓存;
  1. revalidatePath 仅清除服务器端缓存,不会影响客户端本地存储或浏览器缓存。
 

006 Controlling Data Caching 数据缓存控制

在Next.js中灵活控制数据缓存行为,可针对整个文件、单个请求、特定组件粒度调整缓存策略,平衡性能(缓存复用)与数据新鲜度(实时获取)。
🗒️
connection  取代了  unstable_noStore ,以便更好地与 Next.js 的未来发展方向保持一致。 Functions: connection | Next.js
export const revalidate = 60;不起作用(不知道为什么【在生产环境生效,npm run build,npm start后又用,在npm run dev 中不起作用】)

一、文件级缓存配置(全局生效)

适用于文件内所有fetch请求,无需逐个配置,通过导出Next.js保留名称的常量实现,核心有2个关键常量:revalidate(缓存有效期)、dynamic(缓存状态)。

1. revalidate 常量:设置缓存过期时间

  • 作用:统一配置文件内所有fetch请求的缓存复用时长(秒),与fetch函数内的revalidate参数等效,但优先级低于单个请求的显式配置。
  • 要求:必须导出,名称固定为revalidate,值为数字(秒)。
  • 示例代码
  • 说明:60秒内重复访问该页面,Next.js会复用缓存数据;超过60秒后,首次请求会触发新的fetch,更新缓存。

2. dynamic 常量:控制文件级缓存状态

  • 作用:全局控制文件是否启用静态缓存(预渲染)或动态渲染(每次请求重新获取数据),名称固定为dynamic,核心取值如下:
    • 取值
      效果
      适用场景
      auto(默认)
      Next.js自动判断,优先静态缓存
      无特殊实时性要求的页面
      force-dynamic
      禁用文件级缓存,每次请求重新获取所有数据
      实时数据页面(如秒杀、实时榜单)
      force-static
      强制静态缓存,永远复用初始缓存数据
      纯静态内容(如官网静态文案)
  • 示例代码(force-dynamic)

二、单个fetch请求的缓存配置(局部生效)

可单独为某个fetch请求配置缓存策略,优先级高于文件级revalidate/dynamic,核心通过fetch的第二个参数配置:

1. 基础配置示例

三、组件级缓存禁用(精准控制)

当页面包含多个组件,仅需禁用某个组件的缓存时,使用unstable_noStore(已稳定版本为noStore),仅作用于当前组件,不影响其他组件/文件。

1. 使用步骤

  • next/cache导入noStore(旧版本为unstable_noStore);
  • 在组件内调用该函数,即可禁用当前组件的缓存。

2. 示例代码

四、优先级总结

单个fetch请求配置(cache/next.revalidate) > 组件级noStore > 文件级dynamic/revalidate

五、避坑点

  1. revalidate常量必须导出且名称完全一致(大小写敏感),否则Next.js无法识别;
  1. unstable_noStore前缀仅为历史版本标识,新版本直接使用noStore
  1. force-static慎用:一旦设置,数据永远不会更新,除非重新部署或手动清除缓存;
  1. 混合配置时,优先遵循“更细粒度”的规则(如组件级 > 文件级 > 全局)。
007 Making Sense Of The Full Route Cache

008 On-Demand Cache Invalidation with revalidatePath & revalidateTag —按 需缓存失效

一、核心背景:按需缓存失效的价值

传统缓存策略的痛点:
  • 动态模式/无存储函数:完全禁用缓存,性能差;
  • 固定时间重新验证(如 fetch 配置 next: { revalidate: 5 }):数据未变化时仍重复请求,冗余低效。
按需缓存失效优势:仅在数据确有变化时,主动告知 Next.js 刷新指定缓存,兼顾性能与数据时效性。

二、核心 API 1:revalidatePath(按路径失效缓存)

1. 基础功能

清除指定路径关联的缓存数据,支持精准控制页面/布局级缓存失效。

2. 导入方式

3. 核心参数

参数位置
类型
说明
默认值
第一个参数
string
目标路径(如 /messages
-
第二个参数
string
失效范围: - page:仅清除当前页面缓存 - layout:清除路径下所有嵌套页面缓存
page

4. 常用场景示例

场景1:仅清除单个页面缓存

场景2:清除嵌套路径所有缓存

场景3:清除全站缓存

场景4:批量清除多个路径

三、核心 API 2:revalidateTag(按标签失效缓存)

1. 基础功能

为缓存数据打标签,通过标签批量清除关联缓存(无需逐个指定路径)。

2. 完整使用流程

步骤1:导入 API

步骤2:为 fetch 请求分配标签

步骤3:触发标签缓存失效

3. 核心优势

  • 跨页面批量失效:多个页面的 fetch 请求若打了相同标签,调用一次即可全部刷新;
  • 解耦路径与缓存:无需关注数据对应的页面路径,仅通过标签关联。

四、关键对比

特性
revalidatePath
revalidateTag
失效维度
页面路径
数据标签
适用场景
单页面/指定路径缓存刷新
多页面共享数据的缓存批量刷新
灵活性
路径级精准控制
标签级批量控制,更灵活
关联方式
与路由路径强关联
与数据逻辑强关联,与路径解耦

五、实战验证要点

  1. 开发环境需重启服务器确保配置生效;
  1. 验证缓存是否失效:观察 fetch 请求日志(失效后会重新发起请求,未失效则复用缓存);
  1. 标签命名建议:语义化(如 user-dataorder-list),便于维护。

009 Setting Up Request Memoization For Custom Data Sources - 自定义数据源(SQLite)缓存与请求记忆化

核心背景

Next.js 内置对 fetch 函数的缓存/请求去重支持,但自定义数据源(如 SQLite 数据库)无此默认能力,需手动处理:
  1. 生产环境路由缓存导致数据更新不及时;
  1. 同一请求周期内多次调用相同数据获取函数,触发重复数据库查询。

一、核心场景:自定义数据源的缓存需求

  1. 场景引入:此前聚焦外部API(fetch函数)的缓存管理,但实际开发中常直接访问数据库(如SQLite)等自定义数据源,需解决这类场景的缓存与请求优化问题。
  1. 技术栈基础:使用better sequel lite free包操作SQLite数据库,该包支持同步交互,无需异步代码(无async/await、无Promise)。

二、数据获取方式改造

  1. 替换fetch请求:注释原外部API请求代码,调用lib文件夹中的getMessages函数(封装数据库查询逻辑),同时在页面组件和布局组件中均通过该函数获取消息数据。
  1. 数据写入逻辑:在新消息页面的服务器操作中,调用addMessage函数(同样来自lib文件夹),将用户输入的消息存入数据库,实现数据新增与页面展示联动。

三、关键问题:缓存与请求重复

1. 生产环境的“完整路由缓存”问题

环境
缓存状态
数据展示效果
解决方案
开发环境
无完整路由缓存
刷新页面可实时看到新增数据
-
生产环境(npm run build后)
页面预渲染+完整路由缓存
仅显示构建时数据,新增数据不展示
强制页面动态化(需额外配置)或通过缓存控制解决

2. 请求重复问题

  • 问题表现:页面组件和布局组件均调用getMessages,导致每次刷新触发两次相同的SQL查询,浪费资源。
  • 根源:Next.js默认仅对fetch函数支持“请求去重”,自定义数据源无此能力。

四、解决方案:React的cache函数实现请求记忆化

1. 核心原理

  • cache函数来自React库(非Next.js),作用是包裹自定义数据获取函数,在同一请求周期内缓存函数首次执行的结果,后续调用直接复用缓存,避免重复查询。

2. 代码实现步骤

3. 效果验证

  • 改造前:每次刷新页面,数据库接收2次查询请求。
  • 改造后:同一请求周期内,仅首次调用触发1次数据库查询,后续调用复用缓存结果。

五、关键概念辨析

概念
定义
适用场景
请求记忆化(Request Memoization)
同一请求周期内缓存函数结果,避免重复执行
自定义数据源(数据库、本地文件等)的重复查询优化
完整路由缓存(Full Route Cache)
生产环境下Next.js预渲染页面并缓存整页内容
静态页面提速,但需注意动态数据更新问题
数据缓存(Data Cache)
缓存fetch请求结果(Next.js默认支持)
外部API请求的重复调用优化
注意事项cache函数仅在“同一请求周期内”生效(如单次页面刷新),页面重新加载后缓存会重置,需结合Next.js其他缓存策略(如revalidatePath)处理长期数据更新。

010 Setting Up Data Caching For Custom Data Sources - 自定义数据源数据缓存设置

一、核心准备:缓存函数导入与命名处理

  1. 导入来源:从next/缓存模块导入缓存相关函数(视频录制时为“不稳定缓存函数”,未来可能移除“不稳定”标识,仅称“缓存函数”)。
  1. 命名策略:为避免名称冲突(如后续函数名简化为“缓存”),建议给函数分配别名(示例:import { unstableCache as nextCache } from 'next/缓存'),即使函数标记“不稳定”,仍可正常使用。

二、缓存实现:函数包裹与层级作用

  1. 包裹方式:用Next.js缓存函数(如别名nextCache)包裹需要缓存的目标函数,支持多层包裹,各层级作用明确:
      • 内层缓存包裹:用于实现“请求去重”功能。
      • 外层nextCache包裹:让函数返回的数据被Next.js识别并存储到其“数据缓存”中。
  1. 核心逻辑:通过嵌套包裹,同时实现请求去重和数据持久化缓存,提升数据获取效率。

三、关键问题:解决Promise返回导致的错误

  1. 错误原因:Next.js缓存函数(如unstableCache)始终返回包裹缓存数据的Promise,而原有获取消息的代码未处理Promise返回值,导致加载消息页面报错。
  1. 解决方案:在两个关键位置补充async关键字:
      • 接收消息并添加权重的组件。
      • 应用布局文件中(设置异步权重),补充后应用可正常运行。

四、效果验证:确认缓存生效

  1. 验证步骤:清除现有缓存配置→重启开发服务器→重新加载消息页面。
  1. 生效标志:页面刷新时,不再出现“从数据库获取消息”的日志,无论多次刷新均无日志输出,说明数据库数据已被缓存并重复使用。

五、进阶配置:指定缓存键数组

  1. 参数作用:Next.js缓存函数的第二个参数为缓存键数组,用于内部唯一识别缓存数据(示例:nextCache(getMessages, ["messages"])["messages"]即为缓存键)。
  1. 注意事项:此缓存键仅用于Next.js内部识别缓存,与后续会学习的“缓存数据标签”(用于分类管理)不同,不可混淆。

011 Invalidating Custom Data Source Data - 自定义数据源缓存失效解决方案

一、核心问题:缓存导致新数据不显示

  1. 问题场景:从自定义数据源缓存数据后,新增数据(如第四条消息)无法实时显示,刷新页面也无法加载
  1. 问题本质:Next.js 默认开启积极缓存策略,完整路由缓存创建后,开发环境与生产环境均会出现此问题,属于框架默认行为而非 Bug

二、关键解决方案

方案1:使用 revalidatePath 函数主动清除路由缓存

  1. 作用机制:通过指定路径,强制丢弃该路径下页面使用的所有缓存数据,触发数据重新获取与页面重新渲染
  1. 操作步骤
      • 在数据创建逻辑(如“添加新消息”按钮点击事件)后调用 revalidatePath 函数
      • 示例:验证 /messages 路径,清除该页面路由缓存与关联数据缓存
  1. 效果:调用后新增数据需重新加载页面可见,后续新增数据会实时触发缓存清除

方案2:通过 revalidateTag + 标签管理实现精细化缓存失效

  1. 前置配置:使用 next cache(原不稳定缓存)时,传递第三个配置对象参数,支持两类设置:
      • 时间配置:设置秒数,到期后自动重新验证缓存(被动失效)
      • 标签配置:自定义标签数组(如 ['messages-data']),将标签绑定到目标缓存数据
  1. 失效逻辑:调用 revalidateTag 并指定标签,Next.js 会:
      • 丢弃所有绑定该标签的缓存数据
      • 重新执行使用该标签获取数据的页面、布局、组件
      • 自动重新渲染关联内容,无需手动刷新页面
  1. 优势:无需管理具体路由,通过标签实现跨页面、跨组件的批量缓存失效,灵活性更高
  • 这里 nextCache(cache(…))不起作用,只用nextCache()可以

三、核心原理总结

解决方式
作用范围
触发方式
适用场景
revalidatePath
指定路由及关联数据
主动调用函数
单一路由、页面级别的缓存失效
revalidateTag
所有绑定指定标签的缓存
主动调用标签验证
多页面共享数据、跨组件数据的批量缓存失效

012 Module Summary

一、核心学习主题

Next.js 后台数据缓存机制与请求优化策略,聚焦“减少不必要请求、高效管理缓存”核心目标

二、关键知识点

(一)Next.js 内置数据处理能力

  1. 数据获取与缓存联动:使用 fetch 函数调用外部 API 时,框架内置缓存控制逻辑
  1. 缓存与页面渲染关联:缓存数据更新后,依赖该数据的页面会自动重新渲染

(二)缓存控制核心手段

  1. 数据重新验证:可自定义配置数据重新验证规则,控制缓存刷新时机
  1. 自定义缓存管理:支持自主管理缓存策略,适配自有数据源(如数据库)场景
  1. 请求去重实现:借助 React 缓存函数 实现请求去重,避免重复发起相同请求

(三)激进缓存支持

  1. 工具依赖:通过 Next.js 提供的 unstable_cache 函数,为自定义数据源启用激进缓存
  1. 作用:提升数据读取效率,减少服务器压力

(四)缓存重新验证方法

方法
说明
revalidatePath
按页面路径触发缓存重新验证
revalidateTag
按标签(为缓存数据打标)触发缓存重新验证

三、学习建议

  1. 深入学习路径:若需了解缓存底层细节,可参考 Next.js 官方文档
  1. 核心掌握重点:无需深究底层,优先掌握“Next.js 激进缓存特性”及“确保数据更新、页面按需渲染的工具/选项”即可满足常规开发需求
 

📎 参考文章

  • 一些引用
  • 引用文章
 
💡
欢迎您在底部评论区留言,一起交流~
上一篇
08 - NextJS App Optimizations
下一篇
06 - Mutating Data - Deep Dive
Loading...
0%