Skip to content

Commit 15191ee

Browse files
committed
Added Next15 support for fetch revalidate
1 parent 08fff9d commit 15191ee

File tree

4 files changed

+87
-26
lines changed

4 files changed

+87
-26
lines changed

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,48 @@ npm install @fortedigital/nextjs-cache-handler
1414

1515
Package depends on the original `@neshca/cache-handler` package - you can use anything provided by it by using import/require from `@neshca/cache-handler`.
1616

17+
## Next 15 Support
18+
19+
As `@neshca/cache-handler` does not officially support Next 15+ yet, we try to keep up with Next and prepare more or less temporary workarounds. At some point we will either create a fork of `@neshca/cache-handler` to fully support Next 15 or it gets updated by the maintainers. As for now we're building a set of decorators/workarounds you can use to build cache solutions for Next 15. We might need to do a full-blown rework which will be marked with a proper major version upgrade.
20+
21+
### String buffer breaking change
22+
23+
If you use Redis Strings cache handler with Next15+ you need to decorate the default Redis String handler with a buffer converter like this:
24+
25+
```
26+
// ...
27+
const redisCacheHandler = createRedisHandler({
28+
client: redisClient,
29+
keyPrefix: "nextjs:",
30+
});
31+
32+
return {
33+
handlers: [
34+
createBufferStringHandler(redisCacheHandler)
35+
]
36+
}
37+
38+
// ...
39+
```
40+
41+
Read more about this in Handlers section below.
42+
43+
### Revalidate fetch breaking change
44+
45+
Instead of:
46+
47+
```
48+
const { CacheHandler } = require("@neshca/cache-handler");
49+
module.exports = CacheHandler;
50+
```
51+
52+
Use this:
53+
54+
```
55+
const { Next15CacheHandler } = require("@fortedigital/next-15-cache-handler");
56+
module.exports = Next15CacheHandler;
57+
```
58+
1759
## Handlers
1860

1961
### 1. `redis-strings`

packages/nextjs-cache-handler/package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"type": "git",
1111
"url": "git+https://github.com/fortedigital/nextjs-cache-handler.git"
1212
},
13-
"version": "1.1.2-alpha-2",
13+
"version": "1.1.3",
1414
"type": "module",
1515
"license": "MIT",
1616
"description": "Next.js cache handlers",
@@ -22,6 +22,9 @@
2222
},
2323
"typesVersions": {
2424
"*": {
25+
"Next15CacheHandler": [
26+
"dist/next-15-cache-handler.d.ts"
27+
],
2528
"composite": [
2629
"dist/composite.d.ts"
2730
],
@@ -69,7 +72,8 @@
6972
},
7073
"distTags": [
7174
"next13.5",
72-
"next14"
75+
"next14",
76+
"next15"
7377
],
7478
"optionalDependencies": {
7579
"@rollup/rollup-linux-x64-gnu": "^4.37.0"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { CacheHandler } from "@neshca/cache-handler";
2+
import {
3+
CachedFetchValue,
4+
IncrementalCacheValue,
5+
} from "next/dist/server/response-cache";
6+
7+
/*
8+
* Use this handler in Next 15.2.1 and higher after `revalidate` property had been removed from context object.
9+
* https://github.com/caching-tools/next-shared-cache/issues/1027
10+
* https://github.com/vercel/next.js/commit/6a1b6336a3062dfdb1b9dddcee6b836da94fd198
11+
*/
12+
export function Next15CacheHandler() {
13+
return class extends CacheHandler {
14+
async set(
15+
cacheKey: string,
16+
incrementalCacheValue: IncrementalCacheValue | null,
17+
ctx: {
18+
revalidate?: number | false;
19+
fetchCache?: boolean;
20+
fetchUrl?: string;
21+
fetchIdx?: number;
22+
tags?: string[];
23+
} & { neshca_lastModified?: number },
24+
) {
25+
await super.set(cacheKey, incrementalCacheValue, {
26+
...ctx,
27+
revalidate:
28+
ctx.revalidate ||
29+
(incrementalCacheValue as CachedFetchValue)?.revalidate,
30+
});
31+
}
32+
};
33+
}

packages/nextjs-cache-handler/src/handlers/redis-strings.ts

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,7 @@ export default function createHandler({
102102
return;
103103
}
104104

105-
await client.unlink(
106-
getTimeoutRedisCommandOptions(timeoutMs),
107-
keysToDelete,
108-
);
105+
await client.unlink(getTimeoutRedisCommandOptions(timeoutMs), keysToDelete);
109106

110107
const updateTagsOperation = client.hDel(
111108
{ isolated: true, ...getTimeoutRedisCommandOptions(timeoutMs) },
@@ -119,10 +116,7 @@ export default function createHandler({
119116
tagsToDelete,
120117
);
121118

122-
await Promise.all([
123-
updateTtlOperation,
124-
updateTagsOperation,
125-
]);
119+
await Promise.all([updateTtlOperation, updateTagsOperation]);
126120
}
127121

128122
async function revalidateSharedKeys() {
@@ -161,10 +155,7 @@ export default function createHandler({
161155
return;
162156
}
163157

164-
await client.unlink(
165-
getTimeoutRedisCommandOptions(timeoutMs),
166-
keysToDelete,
167-
);
158+
await client.unlink(getTimeoutRedisCommandOptions(timeoutMs), keysToDelete);
168159

169160
const updateTtlOperation = client.hDel(
170161
{
@@ -184,10 +175,7 @@ export default function createHandler({
184175
tagsAndTtlToDelete,
185176
);
186177

187-
await Promise.all([
188-
updateTagsOperation,
189-
updateTtlOperation,
190-
]);
178+
await Promise.all([updateTagsOperation, updateTtlOperation]);
191179
}
192180

193181
const revalidatedTagsKey = keyPrefix + REVALIDATED_TAGS_KEY;
@@ -268,10 +256,7 @@ export default function createHandler({
268256
)
269257
: undefined;
270258

271-
await Promise.all([
272-
setTagsOperation,
273-
setSharedTtlOperation,
274-
]);
259+
await Promise.all([setTagsOperation, setSharedTtlOperation]);
275260

276261
switch (keyExpirationStrategy) {
277262
case "EXAT": {
@@ -306,10 +291,7 @@ export default function createHandler({
306291
}
307292
}
308293

309-
await Promise.all([
310-
setOperation,
311-
expireOperation,
312-
]);
294+
await Promise.all([setOperation, expireOperation]);
313295
},
314296
async revalidateTag(tag) {
315297
assertClientIsReady();

0 commit comments

Comments
 (0)