-
Notifications
You must be signed in to change notification settings - Fork 555
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(cache): improve documentation and
cachedFunction
default optio…
…ns (#1011)
- Loading branch information
Showing
2 changed files
with
183 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,225 @@ | ||
# Cache API | ||
|
||
Nitro provides a powerful caching system built on top of the storage layer. | ||
Nitro provides a powerful caching system built on top of the [storage layer](/guide/introduction/storage). | ||
|
||
## Usage | ||
It stores the data in the `cache` mountpoint. | ||
- In development, it will use the [FS driver](https://unstorage.unjs.io/drivers/fs) writting to `.nitro/cache` or `.nuxt/cache` if using [Nuxt](https://nuxt.com). | ||
- In production, it will use the [memory driver](https://unstorage.unjs.io/drivers/memory) by default. | ||
|
||
To overwrite the production storage, set the `cache` mountpoint using the `storage` option: | ||
|
||
::code-group | ||
```ts [nitro.config.ts] | ||
import { defineNitroConfig } from "nitropack"; | ||
|
||
```js | ||
const cachedFn = cachedEventHandler(fn, options); | ||
export default defineNitroConfig({ | ||
storage: { | ||
cache: { | ||
driver: 'redis', | ||
/* redis connector options */ | ||
} | ||
} | ||
}) | ||
``` | ||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
nitro: { | ||
storage: { | ||
cache: { | ||
driver: 'redis', | ||
/* redis connector options */ | ||
} | ||
} | ||
} | ||
}) | ||
``` | ||
:: | ||
|
||
### Options | ||
To overwrite the `cache` mountpoint in development, use the `devStorage` option to add the `cache` mountpoint. | ||
|
||
- `name`: Handler name. It will be guessed from function name if not provided and fallback to `_` otherwise. | ||
- `group`: Part of cache name. Useful to organize cache storage. | ||
- `getKey`: A function that accepts same arguments of normal function and should generate cache key. If not provided, a built-in hash function will be used. | ||
- `integrity`: A value that changing it, will invalidate all caches for function. By default will be computed from **function code**. | ||
- `maxAge`: Maximum age that cache is valid in seconds. Default is `1` second. | ||
- `staleMaxAge`: 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 updating the cache in the background. | ||
- `swr`: Enable Stale-While-Revalidate behavior. Enabled by default. | ||
- `base`: Name of the storage mointpoint to use for caching (`/cache` by default) | ||
- `shouldInvalidateCache`: A function that returns a boolean to invalidate the current cache and create a new one. | ||
- `shouldBypassCache`: A function that returns a boolean to bypass the current cache without invalidating the existing entry. | ||
## Usage | ||
|
||
::code-group | ||
```ts [Router Handler] | ||
// Cache an API handler | ||
export default cachedEventHandler((event) => { | ||
// My event handler | ||
}, options); | ||
``` | ||
```ts [Function] | ||
const myFn = cachedFunction(() => { | ||
// My function | ||
}, options); | ||
``` | ||
:: | ||
|
||
## Examples | ||
|
||
**Example:** Cache an API handler | ||
If you come from [Nuxt](https://nuxt.com), all the examples below should be placed inside the `server/` directory. | ||
|
||
```js | ||
// routes/cached.ts | ||
const myFn = cachedEventHandler( | ||
async () => { | ||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||
return `Response generated at ${new Date().toISOString()}`; | ||
}, | ||
{ | ||
swr: true, | ||
} | ||
); | ||
### Route Handler | ||
|
||
Cache a route with [stale-while-revalidate](https://www.rfc-editor.org/rfc/rfc5861#section-3) behavior for 10 second: | ||
|
||
```ts [routes/cached.ts] | ||
export default cachedEventHandler(async () => { | ||
return `Response generated at ${new Date().toISOString()}`; | ||
}, { | ||
swr: true, maxAge: 10 | ||
}); | ||
``` | ||
|
||
**Example:** Cache a utility function | ||
The response will be cached for 10 second and a stale value will be sent to the client while the cache is being updated in the background. | ||
|
||
```js | ||
// utils/index.ts | ||
const myFn = cachedFunction( | ||
async () => { | ||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||
return Math.random(); | ||
}, | ||
{ | ||
swr: true, | ||
} | ||
); | ||
The cached answer will be store in development inside `.nitro/cache/handlers/_/*.json`. | ||
|
||
### Function | ||
|
||
Cache for 1 hour the result of a function fetching the GitHub stars for a repository: | ||
|
||
::code-group | ||
```ts [utils/github.ts] | ||
export const cachedGHStars = cachedFunction(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 | ||
}) | ||
``` | ||
```ts [api/stars/[...repo].ts] | ||
export default eventHandler(async (event) => { | ||
const repo = event.context.params.repo | ||
const stars = await cachedGHStars(repo).catch(() => 0) | ||
|
||
**Example:** Enable Cache on a group of routes (**🧪 Experimental!**) | ||
return { repo, stars } | ||
}) | ||
``` | ||
:: | ||
|
||
The stars will be cached in development inside `.nitro/cache/functions/ghStars/<owner>/<repo>.json` with `value` being the number of stars. | ||
|
||
```json | ||
{"expires":1677851092249,"value":43991,"mtime":1677847492540,"integrity":"ZUHcsxCWEH"} | ||
``` | ||
|
||
```js | ||
// nitro.config.ts | ||
|
||
## Route Rules | ||
|
||
This feature enable to add caching routes based on a glob pattern directly in the main configuration file. | ||
|
||
|
||
::alert{type="primary"} | ||
This features is still experimental and may evolve in the future. | ||
:: | ||
|
||
Cache all the blog routes for 1 hour with `stale-while-revalidate` behavior: | ||
|
||
::code-group | ||
```ts [nitro.config.ts] | ||
import { defineNitroConfig } from "nitropack"; | ||
|
||
export default defineNitroConfig({ | ||
routeRules: { | ||
"/blog/**": { | ||
swr: true, | ||
swr: 60 * 60, | ||
// or | ||
cache: { | ||
maxAge: 60 * 60 | ||
} | ||
}, | ||
}, | ||
}); | ||
``` | ||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
routeRules: { | ||
"/blog/**": { | ||
swr: 60 * 60, | ||
// or | ||
cache: { | ||
maxAge: 60 * 60 | ||
} | ||
}, | ||
} | ||
}); | ||
``` | ||
:: | ||
|
||
**Example:** Set cache storage mountpoint for a group of routes (**🧪 Experimental!**) | ||
If we want to use a custom storage mountpoint, we can use the `base` option. Let's store our cache result for the blog routes in a Redis storage for production: | ||
|
||
```js | ||
// nitro.config.ts | ||
::code-group | ||
```ts [nitro.config.ts] | ||
import { defineNitroConfig } from "nitropack"; | ||
|
||
export default defineNitroConfig({ | ||
storage: { | ||
"my-custom-storage": { | ||
redis: { | ||
driver: "redis", | ||
url: "redis://localhost:6379", | ||
}, | ||
}, | ||
routeRules: { | ||
"/blog/**": { | ||
swr: true, | ||
swr: 60 * 60, | ||
cache: { | ||
base: "/my-custom-storage", | ||
base: "redis", | ||
}, | ||
}, | ||
}, | ||
}); | ||
``` | ||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
nitro: { | ||
storage: { | ||
redis: { | ||
driver: "redis", | ||
url: "redis://localhost:6379", | ||
}, | ||
}, | ||
}, | ||
routeRules: { | ||
"/blog/**": { | ||
swr: 60 * 60, | ||
cache: { | ||
base: "redis", | ||
}, | ||
}, | ||
}, | ||
}); | ||
``` | ||
:: | ||
|
||
|
||
## Options | ||
|
||
The `cachedEventHandler` and `cachedFunction` functions accept the following options: | ||
- `name`: Handler name. | ||
- Type: `String` | ||
- Default: guessed from function name if not provided and fallback to `_` otherwise. | ||
- `group`: Part of cache name. Useful to organize cache storage. | ||
- Type: `String` | ||
- Default: `'nitro/handlers'` for handlers and `'nitro/functions'` for functions. | ||
- `getKey`: A function that accepts the same arguments of the function and returns a cache key (`String`). | ||
- Type: `Function` | ||
- Default: If not provided, a built-in hash function will be used. | ||
- `integrity`: A value that invalidates the cache when changed. | ||
- Type: `String` | ||
- Default: computed from **function code**, used in development to invalidate the cache when the function code changes. | ||
- `maxAge`: Maximum age that cache is valid in seconds. | ||
- Type: `Number` | ||
- Default: `1` (second). | ||
- `staleMaxAge`: 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 updating the cache in the background. | ||
- Type: `Number` | ||
- Default: `0` (disabled). | ||
- `swr`: Enable `stale-while-revalidate` behavior. | ||
- Default: `true` | ||
- `base`: Name of the storage mointpoint to use for caching. | ||
- Default: `cache`. | ||
- `shouldInvalidateCache`: A function that returns a `Boolean` to invalidate the current cache and create a new one. | ||
- Type: `Function` | ||
- `shouldBypassCache`: A function that returns a boolean to bypass the current cache without invalidating the existing entry. | ||
- Type: `Function` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters