Skip to content

Commit 642256a

Browse files
committed
Prepared full example
1 parent 3c4770d commit 642256a

File tree

20 files changed

+6733
-3
lines changed

20 files changed

+6733
-3
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ If you need the full Redis package:
3535
**Before (1.x.x):**
3636

3737
```js
38-
const { Next15CacheHandler } = require("@fortedigital/nextjs-cache-handler/next-15-cache-handler");
38+
const {
39+
Next15CacheHandler,
40+
} = require("@fortedigital/nextjs-cache-handler/next-15-cache-handler");
3941
module.exports = new Next15CacheHandler();
4042
```
4143

@@ -106,7 +108,7 @@ If upgrading from Next 14 or earlier, **flush your Redis cache**. Cache formats
106108

107109
## Next 15 Support
108110

109-
`@neshca/cache-handler` does not support Next.js 15+. Prior to 2.0.0, this package provided wrappers and enhancements.
111+
`@neshca/cache-handler` does not support Next.js 15+. Prior to 2.0.0, this package provided wrappers and enhancements.
110112
From version 2.0.0 onward, `@fortedigital/nextjs-cache-handler` is a standalone solution with no dependency on `@neshca/cache-handler`.
111113

112114
We aim to keep up with new Next.js releases and will introduce major changes with appropriate version bumps.
@@ -276,13 +278,19 @@ const bufferStringDecorator =
276278
277279
### 2.x.x
278280
281+
#### Full example
282+
283+
`./examples/redis-minimal`
284+
285+
#### Example `cache-handler.js`.
286+
279287
```js
280288
const { createClient } = require("redis");
281289
const { PHASE_PRODUCTION_BUILD } = require("next/constants");
282290
const createCompositeHandler =
283291
require("@fortedigital/nextjs-cache-handler/composite").default;
284292
const createRedisHandler =
285-
require("@fortedigital/nextjs-cache-handler/buffer-string-decorator").default;
293+
require("@fortedigital/nextjs-cache-handler/redis-strings").default;
286294
const createLruHandler =
287295
require("@fortedigital/nextjs-cache-handler/local-lru").default;
288296
const { CacheHandler } = require("@fortedigital/nextjs-cache-handler");

examples/redis-minimal/.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
NEXT_PRIVATE_DEBUG_CACHE="1"
2+
REDIS_URL="redis://localhost:6379"
3+
REDIS_SINGLE_CONNECTION=true

examples/redis-minimal/.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# vercel
34+
.vercel
35+
36+
# typescript
37+
*.tsbuildinfo
38+
next-env.d.ts

examples/redis-minimal/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
# or
12+
pnpm dev
13+
# or
14+
bun dev
15+
```
16+
17+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18+
19+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20+
21+
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22+
23+
## Learn More
24+
25+
To learn more about Next.js, take a look at the following resources:
26+
27+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29+
30+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31+
32+
## Deploy on Vercel
33+
34+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35+
36+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { createClient } from "redis";
2+
import { PHASE_PRODUCTION_BUILD } from "next/constants.js";
3+
import { CacheHandler } from "@fortedigital/nextjs-cache-handler";
4+
import createLruHandler from "@fortedigital/nextjs-cache-handler/local-lru";
5+
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
6+
import createCompositeHandler from "@fortedigital/nextjs-cache-handler/composite";
7+
8+
const isSingleConnectionModeEnabled = !!process.env.REDIS_SINGLE_CONNECTION;
9+
10+
async function setupRedisClient() {
11+
if (PHASE_PRODUCTION_BUILD !== process.env.NEXT_PHASE) {
12+
try {
13+
const redisClient = createClient({
14+
url: process.env.REDIS_URL,
15+
pingInterval: 10000,
16+
});
17+
18+
redisClient.on("error", (e) => {
19+
if (process.env.NEXT_PRIVATE_DEBUG_CACHE !== undefined) {
20+
console.warn("Redis error", e);
21+
}
22+
if (isSingleConnectionModeEnabled) {
23+
global.cacheHandlerConfig = null;
24+
global.cacheHandlerConfigPromise = null;
25+
}
26+
});
27+
28+
console.info("Connecting Redis client...");
29+
await redisClient.connect();
30+
console.info("Redis client connected.");
31+
32+
if (!redisClient.isReady) {
33+
console.error("Failed to initialize caching layer.");
34+
}
35+
36+
return redisClient;
37+
} catch (error) {
38+
console.warn("Failed to connect Redis client:", error);
39+
if (redisClient) {
40+
try {
41+
redisClient.destroy();
42+
} catch (e) {
43+
console.error(
44+
"Failed to quit the Redis client after failing to connect.",
45+
e
46+
);
47+
}
48+
}
49+
}
50+
}
51+
52+
return null;
53+
}
54+
55+
async function createCacheConfig() {
56+
const redisClient = await setupRedisClient();
57+
const lruCache = createLruHandler();
58+
59+
if (!redisClient) {
60+
const config = { handlers: [lruCache] };
61+
if (isSingleConnectionModeEnabled) {
62+
global.cacheHandlerConfigPromise = null;
63+
global.cacheHandlerConfig = config;
64+
}
65+
return config;
66+
}
67+
68+
const redisCacheHandler = createRedisHandler({
69+
client: redisClient,
70+
keyPrefix: "nextjs:",
71+
});
72+
73+
const config = {
74+
handlers: [
75+
createCompositeHandler({
76+
handlers: [lruCache, redisCacheHandler],
77+
setStrategy: (ctx) => (ctx?.tags.includes("memory-cache") ? 0 : 1),
78+
}),
79+
],
80+
};
81+
82+
if (isSingleConnectionModeEnabled) {
83+
global.cacheHandlerConfigPromise = null;
84+
global.cacheHandlerConfig = config;
85+
}
86+
87+
return config;
88+
}
89+
90+
CacheHandler.onCreation(() => {
91+
if (isSingleConnectionModeEnabled) {
92+
if (global.cacheHandlerConfig) {
93+
return global.cacheHandlerConfig;
94+
}
95+
if (global.cacheHandlerConfigPromise) {
96+
return global.cacheHandlerConfigPromise;
97+
}
98+
}
99+
100+
if (process.env.NODE_ENV === "development") {
101+
const config = { handlers: [createLruHandler()] };
102+
if (isSingleConnectionModeEnabled) {
103+
global.cacheHandlerConfig = config;
104+
}
105+
return config;
106+
}
107+
108+
const promise = createCacheConfig();
109+
if (isSingleConnectionModeEnabled) {
110+
global.cacheHandlerConfigPromise = promise;
111+
}
112+
return promise;
113+
});
114+
115+
export default CacheHandler;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { dirname } from "path";
2+
import { fileURLToPath } from "url";
3+
import { FlatCompat } from "@eslint/eslintrc";
4+
5+
const __filename = fileURLToPath(import.meta.url);
6+
const __dirname = dirname(__filename);
7+
8+
const compat = new FlatCompat({
9+
baseDirectory: __dirname,
10+
});
11+
12+
const eslintConfig = [
13+
...compat.extends("next/core-web-vitals", "next/typescript"),
14+
];
15+
16+
export default eslintConfig;

examples/redis-minimal/next.config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { NextConfig } from "next";
2+
3+
const nextConfig: NextConfig = {
4+
cacheHandler:
5+
process.env.NODE_ENV === "production"
6+
? require.resolve("./cache-handler.mjs")
7+
: undefined,
8+
cacheMaxMemorySize: 0, // disable default in-memory caching
9+
};
10+
11+
export default nextConfig;

0 commit comments

Comments
 (0)