缓存 Cache

Nitro 提供了建立在存储层之上的缓存系统。

缓存事件处理程序

要缓存事件处理程序,您只需使用 defineCachedEventHandler 方法。

它的工作原理类似于 defineEventHandler,但带有第二个 options 参数。

routes/cached.ts
ts
// Cache an API handler
export default defineCachedEventHandler((event) => {
  // My event handler
}, { maxAge: 60 * 60 /* 1 hour */ })

在此示例中,响应将被缓存 1 小时,并且在后台更新缓存时,将向客户端发送过时的值。如果您想立即返回更新后的响应,请设置swr: false

处理缓存响应时,所有传入的请求标头都将被丢弃。如果您定义了“varies”选项,则在缓存和提供响应时只会考虑指定的标头。

有关可用选项的更多详细信息,请参阅 options 部分。

您还可以使用 cachedEventHandler 方法作为 defineCachedEventHandler 的别名。

缓存函数

您还可以使用 defineCachedFunction 函数来缓存函数。这对于缓存不是事件处理程序但属于事件处理程序一部分的函数的结果并在多个处理程序中重复使用它非常有用。

例如,您可能希望将 API 调用的结果缓存一小时:

ts
utils/github.ts
ts
export const cachedGHStars = defineCachedFunction(async (repo: string) => {
  const data: any = await $fetch(`https://api.github.com/repos/${repo}`)

  return data.stargazers_count
}, {
  maxAge: 60 * 60,
  name: 'ghStars',
  getKey: (repo: string) => repo
})

这些星星将会被缓存在开发中的 .nitro/cache/functions/ghStars/<owner>/<repo>.json中,其中value为星星的数量。

json
{ "expires": 1677851092249, "value": 43991, "mtime": 1677847492540, "integrity": "ZUHcsxCWEH" }

您还可以使用 cachedFunction 方法作为 defineCachedFunction 的别名。

Edge workers

在边缘工作者中,实例在每次请求后都会被销毁。Nitro 自动使用 event.waitUntil 来保持实例处于活动状态,同时更新缓存并将响应发送到客户端。

为了确保您的缓存函数在边缘工作者中按预期工作,您应始终使用 defineCachedFunctionevent 作为第一个参数传递给函数。

ts
utils/github.ts
ts
import type { H3Event } from 'h3'

export const cachedGHStars = defineCachedFunction(async (event: H3Event, repo: string) => {
  const data: any = await $fetch(`https://api.github.com/repos/${repo}`)

  return data.stargazers_count
}, {
  maxAge: 60 * 60,
  name: 'ghStars',
  getKey: (event: H3Event, repo: string) => repo
})

这样,该函数将能够在更新缓存时保持实例处于活动状态,而不会减慢对客户端的响应速度。

缓存路由规则

此功能使您能够直接在主配置文件中添加基于 glob 模式的缓存路由。这对于为应用程序的一部分制定全局缓存策略特别有用。

使用 stale-while-revalidate 行为缓存所有博客路由 1 小时:

ts
nitro.config.ts
ts
export default defineNitroConfig({
  routeRules: {
    '/blog/**': { cache: { maxAge: 60 * 60 } },
  },
})

如果我们想使用自定义存储挂载点,我们可以使用base选项。

ts
nitro.config.ts
ts
export default defineNitroConfig({
  storage: {
    redis: {
      driver: 'redis',
      url: 'redis://localhost:6379',
    },
  },
  routeRules: {
    '/blog/**': { cache: { maxAge: 60 * 60, base: 'redis' } },
  },
})

自定义缓存存储

Nitro 将数据存储在 cache: 挂载点中。

要覆盖生产存储,请使用 storage 选项设置 cache 挂载点:

ts
nitro.config.ts
ts
export default defineNitroConfig({
  storage: {
    cache: {
      driver: 'redis',
      /* redis 连接器选项 */
    }
  }
})

在开发中,您还可以使用devStorage选项覆盖缓存挂载点:

ts
nitro.config.ts
ts
export default defineNitroConfig({
  devStorage: {
    cache: {
      driver: 'redis',
      /* redis connector options */
    }
  }
})

选项

cachedEventHandlercachedFunction 函数接受以下选项:

  • base string 用于缓存的存储挂载点的名称。默认为cache
  • name string 如果未提供,则从函数名称进行猜测,否则返回_
  • group string 处理程序的默认设置为nitro/handlers,函数的默认设置为nitro/functions
  • getKey() (...args) => string 接受与原始函数相同的参数并返回缓存键(“字符串”)的函数。
    如果未提供,则将使用内置哈希函数根据函数参数生成键。
  • integrity string 更改时使缓存失效的值。
    默认情况下,它是根据功能代码计算得出的,在开发中使用,当功能代码更改时使缓存失效。
  • maxAge number 缓存有效的最大期限(以秒为单位)。默认为1(秒)。
  • staleMaxAge number 过期缓存的有效最大期限(以秒为单位)。如果设置为 -1,则在缓存在后台更新时,过期值仍会发送到客户端。
    默认为 0(禁用)。
  • swr boolean 启用stale-while-revalidate行为,以在异步重新验证过时的缓存响应的同时提供该响应。
    默认为true
  • shouldInvalidateCache() (..args) => boolean 返回boolean的函数以使当前缓存无效并创建一个新的缓存。
  • shouldBypassCache() (..args) => boolean 返回布尔值的函数以绕过当前缓存而不使现有条目无效。
  • varies string[] 一组要考虑用于缓存的请求标头,了解更多。 如果在多租户环境中使用,您可能需要传递 ['host', 'x-forwarded-host'] 以确保这些标头不会被丢弃,并且每个租户的缓存都是唯一的。

缓存键和失效

当使用 defineCachedFunctiondefineCachedEventHandler 函数时,缓存键使用以下模式生成:

ts
`${options.group}:${options.name}:${options.getKey(...args)}.json`

例如以下函数:

ts
const getAccessToken = defineCachedFunction(() => {
  return String(Date.now())
}, {
  maxAge: 10,
  name: 'getAccessToken',
  getKey: () => 'default'
})

将生成以下缓存键:

ts
nitro:functions:getAccessToken:default.json

您可以使用以下命令使缓存的函数条目无效:

ts
await useStorage('cache').removeItem('nitro:functions:getAccessToken:default.json')