Guide

缓存


¥Cache

Nitro 提供了一个基于存储层构建的缓存系统。

缓存事件处理程序

¥Cached event handlers

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

¥To cache an event handler, you simply need to use the defineCachedEventHandler method.

它的工作原理与 defineEventHandler 类似,但多了一个 options 参数。

¥It works like defineEventHandler but with an additional second options parameter.

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

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

¥With this example, the response will be cached for 1 hour and a stale value will be sent to the client while the cache is being updated in the background. If you want to immediately return the updated response set swr: false.

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

¥::important All incoming request headers are dropped when handling cached responses. If you define the varies option, only the specified headers will be considered when caching and serving the responses. ::

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

¥See the options section for more details about the available options.

你也可以将 cachedEventHandler 方法用作 defineCachedEventHandler 的别名。

缓存函数

¥Cached functions

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

¥You can also cache a function using the defineCachedFunction function. This is useful for caching the result of a function that is not an event handler, but is part of one, and reusing it in multiple handlers.

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

¥For example, you might want to cache the result of an API call for one hour:

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 表示星星数量。

¥The stars will be cached in development inside .nitro/cache/functions/ghStars/<owner>/<repo>.json with value being the number of stars.

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

::important 由于缓存数据被序列化为 JSON,因此缓存函数不能返回任何无法序列化的内容,例如符号、映射、集合……::

¥::important Because the cached data is serialized to JSON, it is important that the cached function does not return anything that cannot be serialized, such as Symbols, Maps, Sets… ::

你也可以将 cachedFunction 方法用作 defineCachedFunction 的别名。

Edge Workers

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

¥In edge workers, the instance is destroyed after each request. Nitro automatically uses event.waitUntil to keep the instance alive while the cache is being updated while the response is sent to the client.

为确保你的缓存函数在边缘工作器中按预期工作,你应始终将 event 作为第一个参数传递给使用 defineCachedFunction 的函数。

¥To ensure that your cached functions work as expected in edge workers, you should always pass the event as the first argument to the function using defineCachedFunction.

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
})

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

¥This way, the function will be able to keep the instance alive while the cache is being updated without slowing down the response to the client.

缓存路由规则

¥Caching route rules

此功能允许你直接在主配置文件中基于 glob 模式添加缓存路由。这对于为应用的某个部分设置全局缓存策略尤其有用。

¥This feature enables you to add caching routes based on a glob pattern directly in the main configuration file. This is especially useful to have a global cache strategy for a part of your application.

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

¥Cache all the blog routes for 1 hour with stale-while-revalidate behavior:

export default defineNitroConfig({
  routeRules: {
    "/blog/**": { cache: { maxAge: 60 * 60 } },
  },
});

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

¥If we want to use a custom storage mount point, we can use the base option.

export default defineNitroConfig({
  storage: {
    redis: {
      driver: "redis",
      url: "redis://localhost:6379",
    },
  },
  routeRules: {
    "/blog/**": { cache: { maxAge: 60 * 60, base: "redis" } },
  },
});

自定义缓存存储

¥Customize cache storage

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

¥Nitro stores the data in the cache: mount point.

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

¥To overwrite the production storage, set the cache mount point using the storage option:

export default defineNitroConfig({
  storage: {
    cache: {
      driver: 'redis',
      /* redis connector options */
    }
  }
})

在开发模式下,你还可以使用 devStorage 选项覆盖缓存挂载点:

¥In development, you can also overwrite the cache mount point using the devStorage option:

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

选项

¥Options

cachedEventHandlercachedFunction 函数接受以下选项:

¥The cachedEventHandler and cachedFunction functions accept the following options:

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

¥::field-group

base
string

Name of the storage mountpoint to use for caching.
Default to cache.

name
string

Guessed from function name if not provided, and falls back to '_' otherwise.

group
string

Defaults to 'nitro/handlers' for handlers and 'nitro/functions' for functions.

getKey()
(...args) => string

A function that accepts the same arguments as the original function and returns a cache key (String).
If not provided, a built-in hash function will be used to generate a key based on the function arguments.

integrity
string

A value that invalidates the cache when changed.
By default, it is computed from function code, used in development to invalidate the cache when the function code changes.

maxAge
number

Maximum age that cache is valid, in seconds.
Default to 1 (second).

staleMaxAge
number

Maximum age that a stale cache is valid, in seconds. If set to -1 a stale value will still be sent to the client while the cache updates in the background.
Defaults to 0 (disabled).

swr
boolean

Enable stale-while-revalidate behavior to serve a stale cached response while asynchronously revalidating it.
Defaults to true.

shouldInvalidateCache()
(..args) => boolean

A function that returns a boolean to invalidate the current cache and create a new one.

shouldBypassCache()
(..args) => boolean

A function that returns a boolean to bypass the current cache without invalidating the existing entry.

varies
string[]

An array of request headers to be considered for the cache, learn more. If utilizing in a multi-tenant environment, you may want to pass ['host', 'x-forwarded-host'] to ensure these headers are not discarded and that the cache is unique per tenant.

::

缓存键和失效

¥Cache keys and invalidation

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

¥When using the defineCachedFunction or defineCachedEventHandler functions, the cache key is generated using the following pattern:

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

例如,以下函数:

¥For example, the following function:

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

将生成以下缓存键:

¥Will generate the following cache key:

nitro:functions:getAccessToken:default.json

你可以使用以下方法使缓存的函数条目无效:

¥You can invalidate the cached function entry with:

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