缓存
Nitro 提供了一个构建于存储层之上的缓存系统,由 ocache 提供支持。
缓存可以存储开销较大的操作结果(渲染后的响应、上游 API 调用、复杂计算),并在之后再次提供这些结果,而无需重新执行操作。Nitro 提供了三种使用方式:
#缓存处理器
要缓存事件处理器,请使用 defineCachedHandler 方法。
它的工作方式类似于 defineHandler,但多了一个用于传入缓存选项的第二个参数。
import { defineCachedHandler } from "nitro/cache";
export default defineCachedHandler((event) => {
return "我会被缓存一小时";
}, { maxAge: 60 * 60 });在此示例中,响应会缓存 1 小时。缓存过期后,下一个请求会等待处理器解析出新的值,然后再返回响应。如果你希望在后台重新验证时立即提供过期响应,请设置 swr: true(请参阅 SWR 行为)。
有关可用选项的更多详情,请参阅选项部分。
Important
maxAge 默认为 1 秒。对于任何确实希望缓存的内容,请务必显式设置此选项。
#处理器可以看到的内容
对于可缓存的请求,处理器接收到的请求数据,恰好就是缓存键所涵盖的数据。在处理器运行前,其他所有内容都会被移除,因此处理器无法根据缓存键无法区分的值来渲染输出,并将其存储在共享键下:
- 请求头会被剥离,除非列在
varies中。这包括if-none-match/if-modified-since(Nitro 会自行处理条件请求)以及traceparent或x-request-id等追踪头。 - 查询参数会被剥离,除非列在
allowQuery中。默认情况下,/page、/page?a=1和/page?utm=x都会共用一个条目,并且处理器内部的url.searchParams为空。 - Cookie会被剥离,除非列在
allowCookies中,并且每个缓存响应中的set-cookie都会被移除。 authorization/proxy-authorization会被剥离,除非设置了allowAuthorization。host是唯一会被重写而非移除的请求头:它携带已解析请求源的主机名,该主机名属于缓存键的一部分。因此,为多个主机名提供服务的处理器会为每个主机名生成一个条目。
对于必须原样到达处理器的请求,请使用 shouldBypassCache。绕过缓存的请求会保留其请求头、Cookie、查询字符串和请求体,且其响应不会被存储。
#自动 HTTP 头
使用 defineCachedHandler 时,Nitro 会自动管理缓存响应上的 HTTP 缓存头:
etag:如果处理器尚未设置,则根据响应体哈希生成弱 ETag(W/"...")。cache-control:根据实际应用于条目的有效期生成,除非处理器已设置此项(请参阅下表)。vary:varies中的每个名称都会合并到响应的Vary中;使用allowCookies时也会加入Cookie。allowQuery不会添加任何内容,因为查询参数已经包含在 URL 中。x-cache:类似 CDN 的缓存状态头(HIT、STALE、REVALIDATED或MISS)。可通过cacheStatusHeader选项自定义。
| 选项 | 合成的 cache-control |
|---|---|
{ maxAge: 60 } | max-age=60 |
{ maxAge: 60, swr: true } | max-age=60, s-maxage=60 |
{ maxAge: 60, swr: true, staleMaxAge: 600 } | max-age=60, s-maxage=60, stale-while-revalidate=600 |
只有设置了 staleMaxAge 时,才会声明 stale-while-revalidate,因为该指令需要一个以秒为单位的数值。设置 swr: true 而未设置 staleMaxAge 时,过期窗口没有限制,因此下游缓存会在 max-age 之后重新验证,而 Nitro 会使用其过期副本响应。
要仅在服务器端缓存,而不向客户端和 CDN 声明 cache-control,请设置 sendCacheControl: false。
Note
永远不会生成 last-modified。 条目填充的时间并不等于内容更改的时间,因此当处理器知道实际修改时间时,应自行设置此请求头。同样,处理器设置的 cache-control 也永远不会被覆盖。
#条件请求(304 Not Modified)
缓存处理器会自动支持条件请求。当客户端发送的 if-none-match 与缓存的 etag 匹配,或者 if-modified-since 的时间等于或晚于处理器设置的 last-modified 时,Nitro 会返回不含响应体的 304 Not Modified 响应。如果两者都存在,则以 if-none-match 为准。
请求验证器会在请求被缩减范围之前捕获,因此处理器永远不会看到它们,也无法自行处理条件请求。
#可缓存的请求
只有 GET 和 HEAD 请求会被缓存。所有其他 HTTP 方法(POST、PUT、DELETE 等)都会自动绕过缓存并直接调用处理器;携带 Range 请求头的请求也会如此。
GET 和 HEAD 会使用单独的条目进行缓存,因为 HEAD 响应不包含响应体。即使使用自定义 getKey,方法仍然是缓存键的一部分。
#请求去重
当缓存正在解析时,如果有多个并发请求命中相同的缓存键,只会运行一次处理器调用。所有并发请求都会等待并共享相同的结果。
共享解析受 maxResolveTime 限制(默认 30 秒)。超时后,所有等待者都会因 TimeoutError 而被拒绝,正在刷新的条目会被移除,并且该键可以再次使用。此外,处理器还会通过 event.req.signal 收到此截止时间,因此你可以将其传递给上游 fetch 调用。
#缓存函数
你也可以使用 defineCachedFunction 缓存函数。这适用于缓存非事件处理器函数的结果,但该函数是事件处理器的一部分,并且需要在多个处理器中复用的情况。
例如,你可能想将 API 调用的结果缓存一小时:
import { defineCachedFunction } from "nitro/cache";
import { defineHandler, type H3Event } from "nitro";
export default defineHandler(async (event) => {
const { repo } = event.context.params;
const stars = await cachedGHStars(repo).catch(() => 0)
return { repo, stars }
});
const cachedGHStars = defineCachedFunction(async (repo: string) => {
const data = await fetch(`https://api.github.com/repos/${repo}`).then(res => res.json());
return data.stargazers_count;
}, {
maxAge: 60 * 60,
name: "ghStars",
getKey: (repo: string) => repo
});星标数会使用缓存存储(默认为内存)进行缓存。缓存键由组、名称和 getKey 的结果生成,而 value 则是星标数。
{"expires":1677851092249,"value":43991,"mtime":1677847492540,"integrity":"ZUHcsxCWEH"}Important
由于缓存数据会被序列化为 JSON,因此缓存函数不能返回无法序列化的内容,例如 Symbols、Maps、Sets……
对于本身就是字节的值(Uint8Array、ArrayBuffer 或任何类型化数组),无需使用钩子即可处理,并且始终会作为 Uint8Array 返回。其存储方式取决于后端:声明了 binary 的后端会原样保存字节,而执行序列化的后端(包括 Nitro 的默认缓存存储)会将其存储为 base64。对象中嵌套的字节不会采用此处理方式;对于这类数据结构,请使用 serialize/transform。
Note
如果你使用 edge workers 托管应用,应遵循以下说明。
在 edge workers 中,实例会在每个请求完成后销毁。Nitro 会自动使用 event.waitUntil,以便在响应发送给客户端的同时,实例仍能保持运行并更新缓存。
为确保缓存函数在 edge workers 中按预期工作,应始终将 event 作为使用 defineCachedFunction 定义的函数的第一个参数传入。
import { defineCachedFunction } from "nitro/cache";
import { defineHandler, type H3Event } from "nitro";
export default defineHandler(async (event) => {
const { repo } = event.context.params;
const stars = await cachedGHStars(event, repo).catch(() => 0)
return { repo, stars }
});
const cachedGHStars = defineCachedFunction(async (event: H3Event, repo: string) => {
const data = await fetch(`https://api.github.com/repos/${repo}`).then(res => res.json());
return data.stargazers_count;
}, {
maxAge: 60 * 60,
name: "ghStars",
getKey: (event: H3Event, repo: string) => repo
});这样,函数就能在更新缓存时保持实例运行,同时不会拖慢返回给客户端的响应。
对于请求不携带 waitUntil 的平台,请改用 waitUntil 选项传递平台钩子。
#选项
defineCachedHandler 和 defineCachedFunction 函数接受以下选项:
#通用选项
以下选项可用于 defineCachedHandler 和 defineCachedFunction:
用于缓存键的存储基路径(前缀),通常与存储挂载点相匹配。 :br
默认为 /cache(存储在 cache: 前缀下)。如果提供数组,读取时会按顺序尝试每个基路径,写入时则会写入所有基路径(多层缓存)。
如果未提供,则根据函数名称猜测;否则回退为 anon_<hash>(根据函数代码计算)。
处理器默认为 'nitro/handlers',函数默认为 'nitro/functions'。
接受与原始函数相同参数并返回缓存键(String)的函数。 :br
如果未提供,则会使用内置哈希函数,根据函数参数生成键。对于缓存处理器,键由请求源、路径和方法生成。 :br :br
自定义 getKey 会替代生成的键,但不会替代请求范围缩减:处理器可以看到哪些内容,仍由 allowQuery、allowCookies 和 varies 决定。
更改时会使缓存失效的值。 :br 默认情况下,它根据函数代码和选项计算,因此更改其中任一项都会静默忽略旧条目,而不是提供旧条目。
缓存有效的最长时间,以秒为单位。 :br
默认为 1(秒)。显式设置为 0 会禁用该处理器或函数的缓存;省略或设为 undefined 时,则回退到默认值。
在 maxAge 过期后,后台重新验证期间仍可提供过期值的最长时间,以秒为单位。仅在启用 swr 时适用。 :br
设置为 0 时,永远不会提供过期值(等同于禁用 swr)。未设置时,过期值可以无限期提供,并且不会写入存储 TTL,因此条目会一直保留,直到后端将其清除。
启用 stale-while-revalidate 行为,在异步重新验证的同时提供过期的缓存值。 :br
启用后,过期的缓存值会立即返回,同时在后台进行重新验证。禁用后,调用方会在前台等待值重新验证完成。 :br
默认为 false。请参阅 SWR 行为。
根据解析后的值为每个条目推导缓存有效期,并覆盖该条目的静态 maxAge / staleMaxAge 选项。返回以秒为单位的数值(maxAge 的简写),或返回可同时覆盖 staleMaxAge 的对象。 :br
适用于携带自身过期时间的值,例如访问令牌:getMaxAge: (entry) => entry.value.expires_in。解析后的值 <= 0 时,会禁用该条目的缓存。对于处理器,entry.value 是 Response,合成的 cache-control 会遵循返回的有效期。
一次共享解析的截止时间,以秒为单位。默认为 30。 :br
超时后,所有等待的调用方都会因 TimeoutError 而被拒绝,并且正在刷新的条目会被移除。设置为 Infinity 或 0 可禁用此限制;对于确实运行缓慢的解析器,请调高此值。
覆盖此处理器或函数所使用的后端。 :br
默认为 Nitro 的缓存存储,它是 Nitro 存储层中 cache: 前缀的适配器。
将后台工作(缓存写入、SWR 刷新、清除操作)交给宿主运行时处理。 :br
优先级高于 event.req.waitUntil。仅在请求不携带此方法的无服务器平台上需要使用。
返回 boolean 的函数,用于使当前缓存失效并创建新缓存。
返回 boolean 的函数,用于绕过当前缓存但不使现有条目失效。 :br
对于处理器,绕过缓存的请求会以未更改的状态到达处理器(包括凭据、Cookie 和完整查询字符串),其响应既不会被存储,也不会带有缓存头。
缓存函数抛出错误时调用的自定义错误处理器。 :br 默认情况下,错误会记录到控制台,并由 Nitro 错误处理器捕获。
#仅适用于处理器的选项
以下选项仅适用于 defineCachedHandler:
为 true 时,跳过完整响应缓存,仅处理条件请求头(if-none-match、if-modified-since),用于返回 304 Not Modified 响应。每个请求都会调用处理器,并以处理器自身设置的 etag / last-modified 作为条件,因此处理器必须自行设置这些值。此模式下不会生成 x-cache 请求头。
作为缓存键变化依据的请求头名称数组。此处列出的请求头在缓存解析期间会保留在请求中,并纳入缓存键,使缓存按请求头值的不同组合进行区分。它们也会合并到响应的 Vary 请求头中。 :br :br
未列在 varies 中的请求头会在调用处理器之前从请求中剥离,以确保缓存命中一致。 :br :br
如果响应自身的 Vary 列出了键中未包含的请求头,则该响应会返回,但不会被存储,因此请确保两个列表保持同步。 :br :br
多租户配置现在无需在此处添加 ['host']:请求源已经是生成的键的一部分。只有当处理器在代理后会读取 x-forwarded-host 时,才需将其添加进来。
允许作为缓存键变化依据的查询参数名称白名单。默认情况下,任何查询参数都不会影响缓存键,也不会传递给处理器,因此 /page?a=1 和 /page?utm=x 会共用一个条目,并且处理器内部的 url.searchParams 为空。 :br :br
设置数组可指定允许的名称(区分大小写,不区分顺序);设置为 true 则会根据完整查询字符串生成键,适用于参数无法预先确定的代理和搜索端点。
参与缓存的 Cookie 名称白名单。列出的 Cookie 会影响缓存键,并保留在处理器所见的 cookie 请求头中。 :br :br
默认情况下不允许任何 Cookie:处理器运行前会剥离 cookie 请求头,并且响应中的任何 set-cookie 请求头都会在缓存或返回前被丢弃,因此每个用户专属的 Cookie(例如会话 ID)永远不会通过缓存泄漏给其他用户。只将其值可安全地在所有命中同一缓存键的用户之间共享的 Cookie 加入白名单(例如 theme 或 locale 偏好),切勿加入用户专属的机密信息。 :br :br
设置此选项会生成 Vary: Cookie,这可能会降低 CDN 和共享代理的命中率。可以考虑改用 allowQuery 将选择放入 URL,或与 sendCacheControl: false 配合使用。
允许 authorization 和 proxy-authorization 到达处理器,并使缓存键随其变化。默认为 false,此时可缓存请求中的这两个请求头都会被剥离。 :br :br
发送相同凭据值的所有客户端会共用一个条目。如果响应绝不能共享,请改用 shouldBypassCache。
是否自动设置 cache-control 响应头。默认为 true。 :br
设置为 false 可仅在服务器端缓存:响应仍会存储并从缓存提供,但不会向客户端和 CDN 声明 cache-control。此设置不会生成 no-store,因此下游缓存仍可能根据自身启发式规则存储响应。
添加缓存状态响应头(X-Cache: HIT | STALE | REVALIDATED | MISS)。默认为 true。传入字符串可使用自定义请求头名称,传入 false 可禁用。
直接流式传输用于填充缓存条目的响应,而不是先进行缓冲。默认为 false。 :br
这可以改善流式渲染的首字节时间,但会导致无法生成合成的 etag(摘要需要完整的响应体),并且会影响响应体中途出错时的恢复。任何不完整内容都不会被存储,后续请求仍会像往常一样使用已存储的条目。
可缓冲并用于存储的最大响应体大小,以字节为单位。更大的响应会像绕过缓存的请求一样直接流式传输,不会被缓存。 :br Nitro 的默认存储未声明单个条目的大小上限,因此默认没有限制。对于代理大小不受你控制的上游响应的任何路由,请设置此选项。
在内置检查的基础上,额外判断响应是否可缓存(内置检查始终适用,且只能进一步收窄缓存范围)。返回 false 可跳过响应缓存;响应仍会返回给调用方,只是不予存储。 :br
此函数在读取和写入时都会运行,可以是异步函数,并且会以安全失败的方式处理:钩子抛出错误时会将响应视为“不可缓存”,并交由 onError 处理。
#仅适用于函数的选项
以下选项仅适用于 defineCachedFunction:
在返回缓存条目之前对其进行转换。返回值会替代缓存值。 :br
条目还会携带每次调用对应的 entry.status("hit"、"stale"、"revalidated" 或 "miss"),用于说明值的提供方式,适用于指标统计或条件逻辑。
在将条目写入存储之前,准备好已解析的值(对应于 transform 的写入侧操作)。适用于函数返回无法原样存储的内容(例如流或类实例)的情况:serialize 会在写入时转换数据,而 transform 会在读取时恢复数据。 :br
每次解析只会运行一次,且去重调用会共享该结果,因此可以安全地读取流等只能使用一次的数据源。
验证缓存条目。返回 false(或解析为 false 的 Promise)会将条目视为无效并触发重新解析。第二个参数包含当前调用的 args,因此可以根据这些参数验证条目。
#SWR 行为
stale-while-revalidate(SWR)模式需要通过 swr 选项显式启用(默认禁用)。了解它与其他选项的交互方式:
swr | maxAge | 行为 |
|---|---|---|
false(默认) | 3600 | 缓存 1 小时;过期时等待新值 |
true | 3600 | 缓存 1 小时;重新验证时提供过期值 |
true | 3600,且设置 staleMaxAge: 600 | 缓存 1 小时;重新验证时最多再提供 10 分钟的过期值 |
true | 3600,且设置 staleMaxAge: 0 | 缓存 1 小时;永远不提供过期值(等同于 swr: false) |
启用 swr 且存在已过期的缓存值时:
event.waitUntil 保持后台刷新继续运行。禁用 swr(默认)且缓存值已过期时:
REVALIDATED)。Tip
当允许数据略微过期时(例如内容页面、列表、第三方 API 镜像),请启用 swr,这样即使缓存过期,响应时间也能保持稳定。对于调用方绝不能收到过期数据的情况(例如访问令牌或逐请求授权检查),请保持禁用。
Warning
设置 swr: true 且未设置 staleMaxAge 时,条目不会携带存储 TTL:最后一个有效值会一直提供,直到后端将其清除。这正是 ISR 模式,但也意味着缓存增长受后端容量而非时间限制。请设置 staleMaxAge,以便最终清理条目。
#缓存键
使用 defineCachedFunction 或 defineCachedHandler 函数时,缓存键会按照以下模式生成:
`${options.base}:${options.group}:${options.name}:${options.getKey(...args)}.json`group 和 name 在进入键之前会经过转义:移除 [A-Za-z0-9_] 之外的字符;如果值因此发生变化,则会附加原始值的哈希。这就是为什么 Nitro 的 nitro/functions 组会显示为 nitrofunctions.<hash>,并且不会与 : 键结构混淆。getKey 的结果是最后一个片段,并且会按原样存储。
例如,以下函数:
import { defineCachedFunction } from "nitro/cache";
const getAccessToken = defineCachedFunction(() => {
return String(Date.now())
}, {
maxAge: 10,
name: "getAccessToken",
getKey: () => "default"
});将存储在类似以下的键下:
cache:nitrofunctions.3aFYDY_G88ZLdElv-hEB0r8snSViMYJ1NbRtlNP9o_0:getAccessToken:default.json默认的 base 为 /cache,存储层会将其规范化为 cache: 前缀(与处理键中其他 / 的方式相同)。
Note
对于缓存处理器,生成的键涵盖请求的源(协议、主机和端口)、URL 路径和方法,以及 varies、allowQuery 和 allowCookies 对应值的哈希。GET 和 HEAD 会分别存储。
Important
如果未提供 name,则会回退为函数源码的哈希;这种方式无法区分由工厂或循环生成的处理器或函数:它们的源码相同,但闭包变量不同,因此会共享同一个键并相互覆盖条目。对于这类情况,请务必显式传入 name(或 getKey)。
Note
如果未提供 getKey,参数会被哈希。不透明值(Blob、ReadableStream、Promise、Request、WeakMap)只会贡献其类型,因此两个不同的值也会共用一个条目;嵌套深度超过 128 层的参数会抛出 RangeError。出现上述任一情况时,请传入一个只读取结果所依赖字段的 getKey。
#哪些内容会被缓存
存储响应之前,会进行以下检查。未通过任一检查的响应仍会返回给调用方,只是永远不会被存储或从缓存提供:
| 检查 | 原因 |
|---|---|
状态不是 200、203、301 或 308 | 只有这些状态对应完整、可复用的表示。错误、204/304、206 范围响应和临时重定向都会被排除。 |
处理器通过 cache-control 选择退出 | 包括 no-store、private、no-cache,或共享有效期为零(如果存在 s-maxage 则使用它,否则使用 max-age)。 |
Vary: * | 除 no-store 之外最强的“禁止共享”信号。 |
Vary 中指定了缓存键之外的请求头 | 存储此响应会将某个变体重放给所有客户端。请将该请求头添加到 varies 中。 |
| 缺少响应体 | 没有可供重放的内容。空的(零字节)200 响应是允许的,并会正常缓存。 |
etag 或 last-modified 等于字符串字面值 "undefined" | 这是将缺失值转换为字符串后通常产生的结果,会破坏条件请求。 |
这些检查始终适用。使用 shouldCache 可以进一步收窄缓存范围。内置检查拒绝的响应也不会获得合成的 cache-control,因此前置 CDN 无法继续缓存错误;而被你自己的 shouldCache 拒绝的响应仍会获得该请求头。
Note
cache-control: must-revalidate 不会选择退出缓存。响应会被存储,并在新鲜时提供,但过期后永远不会提供,因此仅对该响应禁用 SWR。
#缓存失效
可以在运行时以编程方式使缓存条目失效(例如,在底层数据更改时通过 webhook 触发),而无需等待 maxAge 过期。
#.invalidate() 和 .expire() 方法
通过 defineCachedFunction 创建的每个函数都会公开按需重新验证方法:
.invalidate(...args):完全移除缓存条目。下次调用时会重新调用函数,并等待新值。.expire(...args):将缓存条目标记为过期,但不移除它。启用swr时,仍会提供过期值,而下次调用会触发后台刷新;未启用 SWR 时,下次调用会在返回前重新解析。.resolveKeys(...args):解析条目所缓存到的存储键(每个base前缀对应一个)。
参数会传递给 getKey,以生成缓存键。
import { defineCachedFunction } from "nitro/cache";
const cachedGHStars = defineCachedFunction(async (repo: string) => {
const data = await fetch(`https://api.github.com/repos/${repo}`).then(res => res.json());
return data.stargazers_count;
}, {
maxAge: 60 * 60,
name: "ghStars",
getKey: (repo: string) => repo,
});
await cachedGHStars("unjs/nitro"); // populates the cache
await cachedGHStars.expire("unjs/nitro"); // marks the entry as stale
await cachedGHStars.invalidate("unjs/nitro"); // removes the entry
await cachedGHStars("unjs/nitro"); // re-invokes the function如果没有缓存条目与给定参数匹配,.invalidate() 和 .expire() 会正常完成且不报错,并且不会更改存储。两者也会取消该键上正在进行的解析,因此清除前的值不会在清除后写入。
Note
Nitro 的 defineCachedHandler 目前会返回普通事件处理器,并且不会公开这些方法,因此无法按需使缓存路由失效。如果需要此功能,请将开销较大的操作移入由普通 defineHandler 调用的 defineCachedFunction,然后使该函数失效。
#缓存存储
缓存条目使用存储层存储在 cache: 前缀下(该前缀源自默认的 base: "/cache" 选项)。
默认情况下,没有为其配置专用挂载点:条目存储在根存储中,该存储使用内存驱动程序,并且在开发和生产环境中不会跨重启持久化。
要使用持久化后端,请通过 kv 选项设置 cache 挂载点:
import { defineConfig } from "nitro";
export default defineConfig({
kv: {
cache: {
driver: 'redis',
/* redis 连接器选项 */
}
}
})在开发环境中,你也可以使用 $development 配置键覆盖缓存挂载点:
import { defineConfig } from "nitro";
export default defineConfig({
kv: {
cache: {
// 生产环境缓存存储
},
},
$development: {
kv: {
cache: {
// development cache storage
}
}
}
})若要在预渲染时也覆盖它,请同时在 $prerender 中设置。
Note
条目会通过 unstorage 序列化为 JSON,因此 Nitro 的默认缓存存储不会声明 binary。可解码为 UTF-8 的响应体(HTML、JSON、纯文本)无论如何都会以文本形式存储;只有不是有效 UTF-8 的响应体(图片、字体、PDF)才会进行 base64 编码,字节值的缓存函数也会如此。传入你自己的、声明了 binary 的 storage(例如基于驱动程序的 getItemRaw / setItemRaw 创建 ocache 的 createBlobStorage),即可将这些内容保留为字节,并跳过编码、解码和 4/3 倍膨胀。 :br :br
默认后端也不会声明单个条目的大小上限,因此缓存处理器会缓冲任意大小的响应体,除非你设置了 maxBodySize。
#使用路由规则
路由规则允许你直接通过配置,为匹配 glob 模式的所有路由启用缓存。对于应用中某个部分实施全局缓存策略,而无需修改处理器代码时,这尤其有用。
将所有博客路由缓存 1 小时:
import { defineConfig } from "nitro";
export default defineConfig({
routeRules: {
"/blog/**": { cache: { maxAge: 60 * 60 } },
},
});cache 规则接受上文记录的相同处理器选项(swr、staleMaxAge、varies、allowQuery、allowCookies、allowAuthorization、sendCacheControl、cacheStatusHeader、stream、maxBodySize、headersOnly、base、group、name、integrity、maxResolveTime)。shouldCache 等钩子选项仅适用于 defineCachedHandler。
如果要使用自定义缓存存储挂载点,可以使用 base 选项。
import { defineConfig } from "nitro";
export default defineConfig({
kv: {
redis: {
driver: "redis",
url: "redis://localhost:6379",
},
},
routeRules: {
"/blog/**": { cache: { maxAge: 60 * 60, base: "redis" } },
},
});#路由规则快捷方式
你可以使用 swr 快捷方式为路由规则启用 stale-while-revalidate 缓存。swr: 3600 是 cache: { swr: true, maxAge: 3600 } 的简写。设置为 true 时,SWR 会使用默认的 maxAge 1 秒,因此建议传入明确的数值。
import { defineConfig } from "nitro";
export default defineConfig({
routeRules: {
"/blog/**": { swr: 3600 },
"/api/**": { swr: 60 },
},
});要显式禁用某个路由的缓存,请在更具体的模式上设置 cache: false(或 swr: false)。这也会移除从范围更广的模式继承的 cache 规则:
import { defineConfig } from "nitro";
export default defineConfig({
routeRules: {
"/api/**": { swr: 60 },
"/api/realtime/**": { cache: false },
},
});Note
使用路由规则时,缓存处理器会使用组 'nitro/route-rules',而不是默认的 'nitro/handlers';生成的 name 会将条目限定到匹配的路由处理器、HTTP 方法、规则模式和匹配的路由。
Warning
生成的范围在每个进程中都是唯一的。对于持久化缓存存储,重启或启动第二个工作进程都会从全新的条目开始,而不会复用已存储的条目。如果路由规则缓存条目需要跨进程共享,请在规则上设置显式的 name。