Update Redis Cache example with stabilized API (#60800)
This pull request updates the `cache-handler-redis` example with a stabilized API. The updated `next.config.js` now uses the stable `cacheHandler` option instead of the `experimental.incrementalCacheHandlerPath`.
This commit is contained in:
parent
a1610fecd8
commit
3b46f22bb1
5 changed files with 19 additions and 107 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
This example is tailored for self-hosted setups and demonstrates how to use Redis as a shared cache. It is built on the principles of the `@neshca/cache-handler` package, which replaces the default Next.js cache handler and adds advanced caching features.
|
||||
|
||||
Check out this [repository](https://github.com/ezeparziale/nextjs-k8s) that contains a comprehensive setup for Kubernetes.
|
||||
|
||||
## How to use
|
||||
|
||||
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:
|
||||
|
@ -35,11 +37,13 @@ For detailed information on configuration and usage, please refer to our compreh
|
|||
|
||||
- **Handlers:** The `@neshca/cache-handler` package includes [Handlers](https://caching-tools.github.io/next-shared-cache/redis-stack) for seamless integration with Redis.
|
||||
|
||||
- **Create Your Own Handlers:** Take a look at [Custom Redis Handler](https://caching-tools.github.io/next-shared-cache/redis-stack-custom) and use it as a basis to create your own handler.
|
||||
|
||||
- **Redis Server Setup:** Ensure your Redis server is running and properly configured before starting your Next.js application.
|
||||
|
||||
- **Configure Redis Credentials:** Update the `cache-handler-redis*` files with your Redis credentials. Connection details can be found [here](https://redis.io/docs/connect/clients/nodejs/).
|
||||
|
||||
- **Building Without Redis:** To build the app without connecting to Redis, conditionally create the Handler. Check the [documentation](https://caching-tools.github.io/next-shared-cache/configuration/opt-out-cache-on-build) for more details.
|
||||
- **Building Without Redis:** To build the app without connecting to Redis use conditions inside `onCreation` callback. Check the [documentation](https://caching-tools.github.io/next-shared-cache/configuration/opt-out-cache-on-build) for more details.
|
||||
|
||||
## Development and Production Considerations
|
||||
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
const {
|
||||
reviveFromBase64Representation,
|
||||
replaceJsonWithBase64,
|
||||
} = require("@neshca/json-replacer-reviver");
|
||||
const { IncrementalCache } = require("@neshca/cache-handler");
|
||||
const createLruCache = require("@neshca/cache-handler/local-lru").default;
|
||||
const { createClient } = require("redis");
|
||||
|
||||
const REVALIDATED_TAGS_KEY = "sharedRevalidatedTags";
|
||||
|
||||
const client = createClient({
|
||||
url: process.env.REDIS_URL ?? "redis://localhost:6379",
|
||||
});
|
||||
|
||||
client.on("error", (error) => {
|
||||
console.error("Redis error:", error.message);
|
||||
});
|
||||
|
||||
IncrementalCache.onCreation(async () => {
|
||||
// read more about TTL limitations https://caching-tools.github.io/next-shared-cache/configuration/ttl
|
||||
const useTtl = false;
|
||||
|
||||
await client.connect();
|
||||
|
||||
const redisCache = {
|
||||
async get(key) {
|
||||
try {
|
||||
const result = (await client.get(key)) ?? null;
|
||||
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// use reviveFromBase64Representation to restore binary data from Base64
|
||||
return JSON.parse(result, reviveFromBase64Representation);
|
||||
} catch (error) {
|
||||
console.error("cache.get", error);
|
||||
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async set(key, value, ttl) {
|
||||
try {
|
||||
await client.set(
|
||||
key,
|
||||
// use replaceJsonWithBase64 to store binary data in Base64 and save space
|
||||
JSON.stringify(value, replaceJsonWithBase64),
|
||||
useTtl && typeof ttl === "number" ? { EX: ttl } : undefined,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("cache.set", error);
|
||||
}
|
||||
},
|
||||
async getRevalidatedTags() {
|
||||
try {
|
||||
const sharedRevalidatedTags = await client.hGetAll(
|
||||
REVALIDATED_TAGS_KEY,
|
||||
);
|
||||
|
||||
const entries = Object.entries(sharedRevalidatedTags);
|
||||
|
||||
const revalidatedTags = Object.fromEntries(
|
||||
entries.map(([tag, revalidatedAt]) => [tag, Number(revalidatedAt)]),
|
||||
);
|
||||
|
||||
return revalidatedTags;
|
||||
} catch (error) {
|
||||
console.error("cache.getRevalidatedTags", error);
|
||||
}
|
||||
},
|
||||
async revalidateTag(tag, revalidatedAt) {
|
||||
try {
|
||||
await client.hSet(REVALIDATED_TAGS_KEY, {
|
||||
[tag]: revalidatedAt,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("cache.revalidateTag", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const localCache = createLruCache({
|
||||
useTtl,
|
||||
});
|
||||
|
||||
return {
|
||||
cache: [redisCache, localCache],
|
||||
useFileSystem: !useTtl,
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = IncrementalCache;
|
|
@ -13,7 +13,11 @@ client.on("error", (error) => {
|
|||
|
||||
IncrementalCache.onCreation(async () => {
|
||||
// read more about TTL limitations https://caching-tools.github.io/next-shared-cache/configuration/ttl
|
||||
const useTtl = true;
|
||||
function useTtl(maxAge) {
|
||||
const evictionAge = maxAge * 1.5;
|
||||
|
||||
return evictionAge;
|
||||
}
|
||||
|
||||
await client.connect();
|
||||
|
||||
|
@ -28,7 +32,8 @@ IncrementalCache.onCreation(async () => {
|
|||
|
||||
return {
|
||||
cache: [redisCache, localCache],
|
||||
useFileSystem: !useTtl,
|
||||
// read more about useFileSystem limitations https://caching-tools.github.io/next-shared-cache/configuration/use-file-system
|
||||
useFileSystem: false,
|
||||
};
|
||||
});
|
||||
|
|
@ -1,14 +1,9 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
experimental: {
|
||||
incrementalCacheHandlerPath:
|
||||
process.env.NODE_ENV === "production"
|
||||
? require.resolve(
|
||||
// './cache-handler-redis-custom.js' // custom configuration
|
||||
"./cache-handler-redis.js",
|
||||
)
|
||||
: undefined,
|
||||
},
|
||||
cacheHandler:
|
||||
process.env.NODE_ENV === "production"
|
||||
? require.resolve("./cache-handler.js")
|
||||
: undefined,
|
||||
env: {
|
||||
NEXT_PUBLIC_REDIS_INSIGHT_URL:
|
||||
process.env.REDIS_INSIGHT_URL ?? "http://localhost:8001",
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
"devDependencies": {
|
||||
"@neshca/cache-handler": "^0.6",
|
||||
"@neshca/json-replacer-reviver": "^1",
|
||||
"@types/node": "^20.10.4",
|
||||
"@types/react": "^18.2.42",
|
||||
"@types/react-dom": "^18.2.17",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"redis": "latest",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue