Skip to content

Commit 6317140

Browse files
committed
3.1.0
1 parent 726b54c commit 6317140

7 files changed

Lines changed: 924 additions & 716 deletions

File tree

README.md

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,56 @@ const redisHandler = await createRedisHandler({
245245
});
246246
```
247247

248-
#### Redis Cluster (Experimental)
248+
#### Custom value serializer
249+
250+
By default, the handler stores each entry as a JSON string (`JSON.stringify` / `JSON.parse`), matching earlier releases. You can plug in your own wire format to shrink payloads (compression), add encryption, or use another encoding-this package does not ship extra codecs so your dependencies stay minimal.
251+
252+
**Contract**
253+
254+
- `serialize(value)` receives the full cache object Next.js passes in (metadata such as `tags`, `lastModified`, `lifespan`, plus the nested `value` payload). It must return a string suitable for Redis `SET`.
255+
- `deserialize(stored)` receives that string from Redis `GET`. Return a parsed object compatible with the handler, or `null` to treat the key as a miss (stale entries are removed).
256+
257+
The handler normalizes `Buffer` fields inside the payload to strings before `serialize`, and restores buffers after `deserialize`, so a plain `JSON.stringify` / `JSON.parse` round trip remains valid.
258+
259+
**Default export for reuse**
260+
261+
You can import the built-in serializer if you want to wrap or compare behavior:
262+
263+
```js
264+
import createRedisHandler, {
265+
jsonCacheValueSerializer,
266+
} from "@fortedigital/nextjs-cache-handler/redis-strings";
267+
```
268+
269+
**Example: gzip + base64**
270+
271+
Useful when cache entries are large text (RSC payloads, HTML). Uses Node’s built-in `zlib`; `gzipSync` / `gunzipSync` run on the server during cache reads and writes-profile if your traffic is very hot.
272+
273+
```js
274+
import { gzipSync, gunzipSync } from "node:zlib";
275+
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
276+
277+
const redisCacheHandler = createRedisHandler({
278+
client: redisClient,
279+
keyPrefix: "nextjs:",
280+
valueSerializer: {
281+
serialize: (value) => gzipSync(JSON.stringify(value)).toString("base64"),
282+
deserialize: (stored) => {
283+
const parsed = JSON.parse(
284+
gunzipSync(Buffer.from(stored, "base64")).toString("utf-8"),
285+
);
286+
return parsed;
287+
},
288+
},
289+
});
290+
```
291+
292+
**Operational notes**
293+
294+
- Changing `valueSerializer` (or toggling compression) makes existing Redis keys unreadable until you flush those keys or run a migration; plan a key prefix bump or cache clear on deploy.
295+
- Tag maps and TTL sidecar hashes are still stored as JSON by the handler; only the main entry value uses your serializer.
296+
297+
#### Redis Cluster
249298

250299
```js
251300
import { createCluster } from "@redis/client";
@@ -276,8 +325,6 @@ const redisCacheHandler = createRedisHandler({
276325
});
277326
```
278327

279-
**Note:** Redis Cluster support is currently experimental and may have limitations or unexpected bugs. Use it with caution.
280-
281328
### Using ioredis
282329

283330
If you prefer using `ioredis` instead of `@redis/client`, you can use the `ioredisAdapter` helper.

examples/redis-minimal/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
},
1515
"dependencies": {
1616
"@fortedigital/nextjs-cache-handler": "workspace:*",
17-
"ioredis": "^5.9.3",
18-
"next": "16.1.6",
17+
"ioredis": "^5.10.1",
18+
"next": "16.2.1",
1919
"react": "19.2.4",
2020
"react-dom": "19.2.4",
2121
"redis": "^5.11.0"
@@ -26,7 +26,7 @@
2626
"@types/react": "19.2.14",
2727
"@types/react-dom": "19.2.3",
2828
"eslint": "^9",
29-
"eslint-config-next": "16.1.6",
29+
"eslint-config-next": "16.2.1",
3030
"tailwindcss": "^4",
3131
"typescript": "^5"
3232
},

packages/nextjs-cache-handler/package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"next",
1919
"redis"
2020
],
21-
"version": "3.0.1",
21+
"version": "3.1.0",
2222
"type": "module",
2323
"license": "MIT",
2424
"description": "Next.js cache handlers",
@@ -110,7 +110,7 @@
110110
},
111111
"dependencies": {
112112
"cluster-key-slot": "1.1.2",
113-
"lru-cache": "11.2.6",
113+
"lru-cache": "11.2.7",
114114
"p-limit": "^7.3.0"
115115
},
116116
"devDependencies": {
@@ -119,17 +119,17 @@
119119
"@types/node": "22.19.11",
120120
"eslint": "^8.57.1",
121121
"eslint-config-prettier": "^9.1.2",
122-
"globals": "^16.5.0",
123-
"ioredis": "^5.9.3",
124-
"jest": "^30.2.0",
122+
"globals": "^17.4.0",
123+
"ioredis": "^5.10.1",
124+
"jest": "^30.3.0",
125125
"prettier": "^3.8.1",
126-
"prettier-plugin-packagejson": "2.5.22",
126+
"prettier-plugin-packagejson": "3.0.2",
127127
"rimraf": "6.1.3",
128128
"ts-jest": "^29.4.6",
129129
"tsup": "^8.5.1",
130130
"tsx": "4.21.0",
131131
"typescript": "^5.9.3",
132-
"typescript-eslint": "^8.56.0"
132+
"typescript-eslint": "^8.57.2"
133133
},
134134
"peerDependencies": {
135135
"@redis/client": ">= 5.8.3",
@@ -145,7 +145,7 @@
145145
"next16"
146146
],
147147
"optionalDependencies": {
148-
"@rollup/rollup-linux-x64-gnu": "^4.59.0"
148+
"@rollup/rollup-linux-x64-gnu": "^4.60.0"
149149
},
150150
"engines": {
151151
"node": ">=22.0.0"

packages/nextjs-cache-handler/src/functions/nesh-classic-cache.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { Revalidate } from "../handlers/cache-handler.types";
44
import { workAsyncStorage } from "next/dist/server/app-render/work-async-storage.external.js";
55
import type { IncrementalCache } from "next/dist/server/lib/incremental-cache";
66
import { CacheHandler } from "../handlers/cache-handler";
7-
import { CACHE_ONE_YEAR } from "next/dist/lib/constants";
87
import { CachedRouteKind } from "next/dist/server/response-cache";
98

9+
const CACHE_ONE_YEAR = 31536000;
10+
1011
declare global {
1112
var __incrementalCache: IncrementalCache | undefined;
1213
}

packages/nextjs-cache-handler/src/instrumentation/register-initial-cache.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { promises as fsPromises } from "node:fs";
22
import path from "node:path";
33
import os from "node:os";
44
import { PRERENDER_MANIFEST, SERVER_DIRECTORY } from "next/constants.js";
5-
import { CACHE_ONE_YEAR } from "next/dist/lib/constants.js";
65
import type { PrerenderManifest } from "next/dist/build";
76
import {
87
CachedFetchValue,
@@ -15,6 +14,8 @@ import { getTagsFromHeaders } from "../helpers/getTagsFromHeaders";
1514
import { Revalidate } from "../handlers/cache-handler.types";
1615
import pLimit from "p-limit";
1716

17+
const CACHE_ONE_YEAR = 31536000;
18+
1819
type CacheHandlerType = typeof import("../handlers/cache-handler").CacheHandler;
1920

2021
type NextRouteMetadata = {

0 commit comments

Comments
 (0)