Skip to content

Commit d174698

Browse files
H01001000icyJoseph
andauthored
docs: cacheHandlers use object instead of class (#86022)
<!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change(s) that you're making: ## For Contributors ### Improving Documentation - Run `pnpm prettier-fix` to fix formatting issues before opening the PR. - Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide ### Fixing a bug - Related issues linked using `fixes #number` - Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ### Adding a feature - Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas) - Related issues/discussions are linked using `fixes #number` - e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) - Documentation added - Telemetry added. In case of a feature if it's used or not. - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ## For Maintainers - Minimal description (aim for explaining to someone not on the team to understand the PR) - When linking to a Slack thread, you might want to share details of the conclusion - Link both the Linear (Fixes NEXT-xxx) and the GitHub issues - Add review comments if necessary to explain to the reviewer the logic behind a change ### What? ### Why? ### How? Closes NEXT- Fixes # --> This PR fixes the docs' example where it used class (like cacheHandler (no s)), but cacheHandlers expect an object. --------- Co-authored-by: Joseph <[email protected]>
1 parent 1587978 commit d174698

File tree

1 file changed

+30
-32
lines changed

1 file changed

+30
-32
lines changed

docs/01-app/03-api-reference/05-config/01-next-config-js/cacheHandlers.mdx

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ import type { NextConfig } from 'next'
4141

4242
const nextConfig: NextConfig = {
4343
cacheHandlers: {
44-
default: './cache-handlers/default-handler.js',
45-
remote: './cache-handlers/remote-handler.js',
44+
default: require.resolve('./cache-handlers/default-handler.js'),
45+
remote: require.resolve('./cache-handlers/remote-handler.js'),
4646
},
4747
}
4848

@@ -52,8 +52,8 @@ export default nextConfig
5252
```js filename="next.config.js" switcher
5353
module.exports = {
5454
cacheHandlers: {
55-
default: './cache-handlers/default-handler.js',
56-
remote: './cache-handlers/remote-handler.js',
55+
default: require.resolve('./cache-handlers/default-handler.js'),
56+
remote: require.resolve('./cache-handlers/remote-handler.js'),
5757
},
5858
}
5959
```
@@ -91,7 +91,7 @@ Returns a `CacheEntry` object if found, or `undefined` if not found or expired.
9191
Your `get` method should retrieve the cache entry from storage, check if it has expired based on the `revalidate` time, and return `undefined` for missing or expired entries.
9292

9393
```js
94-
class CacheHandler {
94+
const cacheHandler = {
9595
async get(cacheKey, softTags) {
9696
const entry = cache.get(cacheKey)
9797
if (!entry) return undefined
@@ -103,7 +103,7 @@ class CacheHandler {
103103
}
104104

105105
return entry
106-
}
106+
},
107107
}
108108
```
109109

@@ -127,14 +127,14 @@ Returns `Promise<void>`.
127127
Your `set` method must await the `pendingEntry` promise before storing it, since the cache entry may still be generating when this method is called. Once resolved, store the entry in your cache system.
128128

129129
```js
130-
class CacheHandler {
130+
const cacheHandler = {
131131
async set(cacheKey, pendingEntry) {
132132
// Wait for the entry to be ready
133133
const entry = await pendingEntry
134134

135135
// Store in your cache system
136136
cache.set(cacheKey, entry)
137-
}
137+
},
138138
}
139139
```
140140

@@ -153,11 +153,11 @@ Returns `Promise<void>`.
153153
For in-memory caches, this can be a no-op. For distributed caches, use this to sync tag state from an external service or database before processing requests.
154154

155155
```js
156-
class CacheHandler {
156+
const cacheHandler = {
157157
async refreshTags() {
158158
// For in-memory cache, no action needed
159159
// For distributed cache, sync tag state from external service
160-
}
160+
},
161161
}
162162
```
163163

@@ -182,14 +182,14 @@ Returns:
182182
If you're not tracking tag revalidation timestamps, return `0`. Otherwise, find the most recent revalidation timestamp across all the provided tags. Return `Infinity` if you prefer to handle soft tag checking in the `get` method.
183183

184184
```js
185-
class CacheHandler {
185+
const cacheHandler = {
186186
async getExpiration(tags) {
187187
// Return 0 if not tracking tag revalidation
188188
return 0
189189

190190
// Or return the most recent revalidation timestamp
191191
// return Math.max(...tags.map(tag => tagTimestamps.get(tag) || 0));
192-
}
192+
},
193193
}
194194
```
195195

@@ -213,15 +213,15 @@ Returns `Promise<void>`.
213213
When tags are revalidated, your handler should invalidate all cache entries that have any of those tags. Iterate through your cache and remove entries whose tags match the provided list.
214214

215215
```js
216-
class CacheHandler {
216+
const cacheHandler = {
217217
async updateTags(tags, durations) {
218218
// Invalidate all cache entries with matching tags
219219
for (const [key, entry] of cache.entries()) {
220220
if (entry.tags.some((tag) => tags.includes(tag))) {
221221
cache.delete(key)
222222
}
223223
}
224-
}
224+
},
225225
}
226226
```
227227

@@ -264,7 +264,7 @@ Here's a minimal implementation using a `Map` for storage. This example demonstr
264264
const cache = new Map()
265265
const pendingSets = new Map()
266266

267-
module.exports = class MemoryCacheHandler {
267+
module.exports = {
268268
async get(cacheKey, softTags) {
269269
// Wait for any pending set operation to complete
270270
const pendingPromise = pendingSets.get(cacheKey)
@@ -284,7 +284,7 @@ module.exports = class MemoryCacheHandler {
284284
}
285285

286286
return entry
287-
}
287+
},
288288

289289
async set(cacheKey, pendingEntry) {
290290
// Create a promise to track this set operation
@@ -304,16 +304,16 @@ module.exports = class MemoryCacheHandler {
304304
resolvePending()
305305
pendingSets.delete(cacheKey)
306306
}
307-
}
307+
},
308308

309309
async refreshTags() {
310310
// No-op for in-memory cache
311-
}
311+
},
312312

313313
async getExpiration(tags) {
314314
// Return 0 to indicate no tags have been revalidated
315315
return 0
316-
}
316+
},
317317

318318
async updateTags(tags, durations) {
319319
// Implement tag-based invalidation
@@ -322,7 +322,7 @@ module.exports = class MemoryCacheHandler {
322322
cache.delete(key)
323323
}
324324
}
325-
}
325+
},
326326
}
327327
```
328328

@@ -333,15 +333,13 @@ For durable storage like Redis or a database, you'll need to serialize the cache
333333
```js filename="cache-handlers/redis-handler.js"
334334
const { createClient } = require('redis')
335335

336-
module.exports = class RedisCacheHandler {
337-
constructor() {
338-
this.client = createClient({ url: process.env.REDIS_URL })
339-
this.client.connect()
340-
}
336+
const client = createClient({ url: process.env.REDIS_URL })
337+
client.connect()
341338

339+
module.exports = {
342340
async get(cacheKey, softTags) {
343341
// Retrieve from Redis
344-
const stored = await this.client.get(cacheKey)
342+
const stored = await client.get(cacheKey)
345343
if (!stored) return undefined
346344

347345
// Deserialize the entry
@@ -361,7 +359,7 @@ module.exports = class RedisCacheHandler {
361359
expire: data.expire,
362360
revalidate: data.revalidate,
363361
}
364-
}
362+
},
365363

366364
async set(cacheKey, pendingEntry) {
367365
const entry = await pendingEntry
@@ -383,7 +381,7 @@ module.exports = class RedisCacheHandler {
383381
// Combine chunks and serialize for Redis storage
384382
const data = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)))
385383

386-
await this.client.set(
384+
await client.set(
387385
cacheKey,
388386
JSON.stringify({
389387
value: data.toString('base64'),
@@ -395,23 +393,23 @@ module.exports = class RedisCacheHandler {
395393
}),
396394
{ EX: entry.expire } // Use Redis TTL for automatic expiration
397395
)
398-
}
396+
},
399397

400398
async refreshTags() {
401399
// No-op for basic Redis implementation
402400
// Could sync with external tag service if needed
403-
}
401+
},
404402

405403
async getExpiration(tags) {
406404
// Return 0 to indicate no tags have been revalidated
407405
// Could query Redis for tag expiration timestamps if tracking them
408406
return 0
409-
}
407+
},
410408

411409
async updateTags(tags, durations) {
412410
// Implement tag-based invalidation if needed
413411
// Could iterate over keys with matching tags and delete them
414-
}
412+
},
415413
}
416414
```
417415

0 commit comments

Comments
 (0)